成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

線程切換是如何給 CPU 洗腦的?

商務(wù)辦公
計(jì)算機(jī)系統(tǒng)中有很多程序員習(xí)以為常但又十分神秘的存在:函數(shù)調(diào)用、系統(tǒng)調(diào)用、進(jìn)程切換、線程切換以及中斷處理。

[[413668]]

大家好,我是小風(fēng)哥。

計(jì)算機(jī)系統(tǒng)中有很多程序員習(xí)以為常但又十分神秘的存在:函數(shù)調(diào)用、系統(tǒng)調(diào)用、進(jìn)程切換、線程切換以及中斷處理。

函數(shù)調(diào)用能讓程序員提高代碼可復(fù)用性,系統(tǒng)調(diào)用能讓程序員向操作系統(tǒng)發(fā)起請(qǐng)求,進(jìn)程線程切換讓多任務(wù)成為可能,中斷處理能讓操作系統(tǒng)管理外部設(shè)備。

這些機(jī)制是計(jì)算機(jī)系統(tǒng)中的基石,可是你知道這些機(jī)制是如何實(shí)現(xiàn)的嗎?

這篇文章將告訴你答案,其背后的實(shí)現(xiàn)如此優(yōu)雅且一致。

速度與激。。寄存器

你有沒有想過(guò),CPU為什么需要寄存器?

原因很簡(jiǎn)單:速度。

通常CPU可以在一個(gè)時(shí)鐘周期內(nèi)訪問(wèn)一次寄存器,CPU訪問(wèn)內(nèi)存的速度大概要比訪問(wèn)寄存器慢100倍左右。

因此如果CPU沒有寄存器而完全依賴內(nèi)存的話,那么計(jì)算速度將比現(xiàn)在慢的多。

作為程序員來(lái)說(shuō),當(dāng)我們使用高級(jí)語(yǔ)言編寫的程序時(shí),其操作的數(shù)據(jù)都存放在內(nèi)存中,而對(duì)于負(fù)責(zé)運(yùn)算類的機(jī)器指令來(lái)說(shuō)其操作的數(shù)據(jù)都存放在寄存器中。

實(shí)際上寄存器和內(nèi)存沒有什么本質(zhì)的區(qū)別,都是用來(lái)存儲(chǔ)信息的。

當(dāng)然,除了臨時(shí)保存中間計(jì)算結(jié)果之外,還有很多有趣的寄存器。根據(jù)用途,寄存器有很多類型,但是,我們感興趣的有以下幾種寄存器。

棧寄存器:Stack Pointer

函數(shù)在運(yùn)行時(shí)都有一個(gè)運(yùn)行時(shí)棧,對(duì)于棧來(lái)說(shuō)最重要的信息就是棧頂,棧頂信息就保存在棧寄存器中,stack pointer,通過(guò)該寄存器就能跟蹤函數(shù)的調(diào)用棧。

最為程序員我們知道,函數(shù)在運(yùn)行時(shí)會(huì)有一塊獨(dú)立的內(nèi)存空間,用來(lái)保存函數(shù)內(nèi)定義的局部變量、傳遞的參數(shù)以及返回值信息等,這塊獨(dú)立的內(nèi)存空間就叫棧幀,隨著函數(shù)調(diào)用層次的加深,棧幀也隨之增加;當(dāng)函數(shù)調(diào)用完成后棧幀由按照相反的順序依次減少,這些棧幀就構(gòu)成了棧區(qū)。

函數(shù)的運(yùn)行時(shí)棧信息是關(guān)于程序運(yùn)行狀態(tài)最重要的信息之一。

那么其它的之一呢?

指令地址寄存器:Program Counter

這類寄存器的名稱比較多,基于歷史原因,大部分將其稱為Program Counter,PC,即我們熟悉的程序計(jì)數(shù)器;在x86下則被稱為Instruction Pointer,IP,怎么稱呼不重要,重要的是理解其作用。在本文中統(tǒng)一將其稱為PC寄存器。

我們都知道,程序員用高級(jí)語(yǔ)言編寫的程序最終通過(guò)編譯器生成最終的機(jī)器指令,那么一個(gè)問(wèn)題就是在茫茫的機(jī)器指令海洋中,CPU怎么知道該去執(zhí)行哪條機(jī)器指令呢?

原來(lái),奧秘就藏在指令地址寄存器中。

程序在啟動(dòng)時(shí)會(huì)把機(jī)器指令的首地址寫入到PC寄存器中,這樣CPU需要做的就是根據(jù)PC寄存器中的地址去內(nèi)存中取出指令。

通常來(lái)說(shuō),指令都是順序執(zhí)行的,也就是說(shuō)PC寄存器中的值不斷的+1,但對(duì)于一些涉及控制轉(zhuǎn)移的機(jī)器指令來(lái)說(shuō),這些指令會(huì)把一個(gè)新的指令地址放到PC寄存器中,這包括分支跳轉(zhuǎn)——也就是if語(yǔ)句、函數(shù)調(diào)用以及返回等。

控制了CPU的PC寄存器就掌握了CPU的航向,機(jī)器指令自己會(huì)根據(jù)執(zhí)行狀態(tài)指揮CPU接下來(lái)該去執(zhí)行哪些指令,這才是真正的自動(dòng)駕駛,非常amazing有沒有!

指令地址寄存器是關(guān)于程序運(yùn)行時(shí)狀態(tài)另一個(gè)最重要的信息之一。

狀態(tài)寄存器:Status Register

CPU內(nèi)部除了上述兩類寄存器外,還有一類狀態(tài)寄存器,Status Register;在x86架構(gòu)下被稱為FLAGS register,ARM架構(gòu)下被稱為application program status register,以下統(tǒng)稱狀態(tài)寄存器。

從名字也能看出來(lái),該寄存器是保存狀態(tài)信息的,有什么有趣的狀態(tài)信息呢?

比如對(duì)于涉及到算術(shù)運(yùn)算的指令來(lái)說(shuō),其在執(zhí)行過(guò)程中可能會(huì)產(chǎn)生進(jìn)位,也可能會(huì)溢出,那么這些信息就保存在狀態(tài)寄存器中。

除此之外,你肯定聽說(shuō)過(guò)程序的執(zhí)行一般有兩種模式:內(nèi)核態(tài)和用戶態(tài)。

對(duì)于大部分的程序員其編寫的應(yīng)用程序運(yùn)行在用戶態(tài),在用戶態(tài)下不能執(zhí)行特權(quán)指令,比如你沒辦法寫一個(gè)程序直接去控制系統(tǒng)中的各種硬件資源。

而在內(nèi)核態(tài)下,CPU可以執(zhí)行任意的特權(quán)指令,內(nèi)核就工作在內(nèi)核態(tài),因此內(nèi)核可以掌控一切。關(guān)于用戶態(tài)內(nèi)核態(tài)完整的闡述參見博主深入理解操作系統(tǒng)第2章,關(guān)注公眾號(hào)碼農(nóng)的荒島求生并回復(fù)操作系統(tǒng)即可。

那么我們?cè)趺粗喇?dāng)前程序運(yùn)行在哪種狀態(tài)呢?

答案就在CPU內(nèi)部的狀態(tài)寄存器中,該寄存器中有特定的比特位來(lái)標(biāo)記當(dāng)前CPU正工作在哪種模式下。

現(xiàn)在你應(yīng)該知道寄存器的重要作用了吧。

上下文:Context

通過(guò)這些寄存器,你可以知道程序運(yùn)行到當(dāng)前這一刻時(shí)最細(xì)粒度的切面,這一時(shí)刻這些寄存器中保存的所有信息就是我們通常所說(shuō)的上下文,context。

上下文的作用是什么呢?

只要你能拿到一個(gè)程序運(yùn)行時(shí)的上下文并保存起來(lái),那么你可以隨時(shí)暫停該程序的運(yùn)行,也可以隨時(shí)利用該信息恢復(fù)該程序的運(yùn)行。

為什么要保存和恢復(fù)上下文信息呢?原因就在于CPU的個(gè)數(shù)是有限的,這就意味一個(gè)CPU可能會(huì)執(zhí)行多個(gè)進(jìn)程,即這些進(jìn)程要共享該CPU資源,更具體的是CPU的計(jì)算資源和這里所說(shuō)的各種寄存器。

這是實(shí)現(xiàn)函數(shù)調(diào)用、系統(tǒng)調(diào)用、進(jìn)程切換、線程切換以及中斷處理的基本機(jī)制。

而程序在運(yùn)行過(guò)程中逃不出函數(shù)調(diào)用、系統(tǒng)調(diào)用、進(jìn)程切換、線程切換以及中斷處理這幾項(xiàng)操作,由此可見上下文信息的保存和恢復(fù)在計(jì)算機(jī)科學(xué)中重要的作用。

那么上下文信息又該如何保存呢?保存到哪里呢?又該怎么恢復(fù)呢?函數(shù)調(diào)用、系統(tǒng)調(diào)用、進(jìn)程切換、線程切換以及中斷處理又是怎樣實(shí)現(xiàn)的呢?

游戲與棧

經(jīng)常玩游戲的同學(xué)應(yīng)該都知道,游戲里有主線,有時(shí)在主線任務(wù)中還要去完成一些支線任務(wù),也就是說(shuō)任務(wù)A依賴任務(wù)B,任務(wù)B依賴任務(wù)C,那么任務(wù)的依賴關(guān)系是這樣的:

  1. A -> B -> C 

那么很顯然只有完成任務(wù)C你才能繼續(xù)任務(wù)B,完成任務(wù)B才能繼續(xù)任務(wù)A,因此任務(wù)完成順序是這樣的:

  1. C-> B -> A 

我們可以看到任務(wù)完成順序和任務(wù)依賴順序是相反的:先來(lái)的反而后完成。

這天然適合棧來(lái)表示。

這里特別值得注意的是,棧是一種機(jī)制,和其本身是怎么實(shí)現(xiàn)的沒有關(guān)系,你可以用軟件來(lái)實(shí)現(xiàn)棧,也可以用硬件來(lái)實(shí)現(xiàn)棧。

棧是一種如此簡(jiǎn)單的結(jié)構(gòu),卻又如此強(qiáng)大。棧是實(shí)現(xiàn)計(jì)算機(jī)系統(tǒng)的一種極為重要的基礎(chǔ)機(jī)制,接下來(lái)的講解就能讓你意識(shí)到棧的重要作用。

函數(shù)調(diào)用與運(yùn)行時(shí)棧

函數(shù)是編程語(yǔ)言中最重要的概念之一,函數(shù)讓代碼復(fù)用成為可能,你知道函數(shù)調(diào)用是如何實(shí)現(xiàn)的嗎?

函數(shù)調(diào)用的難點(diǎn)在于CPU不能在平鋪直敘的往前依次順序的執(zhí)行機(jī)器指令,而是要跳轉(zhuǎn)到被調(diào)函數(shù)的第一條機(jī)器指令,執(zhí)行完該函數(shù)后還要跳轉(zhuǎn)回來(lái)。

當(dāng)你從A函數(shù)跳轉(zhuǎn)到B函數(shù)時(shí),A函數(shù)被暫停運(yùn)行,當(dāng)被調(diào)函數(shù)執(zhí)行完后A函數(shù)繼續(xù)運(yùn)行。

因此這里就涉及到A函數(shù)的狀態(tài)保存與狀態(tài)恢復(fù)。

函數(shù)的運(yùn)行時(shí)狀態(tài)有什么呢?

主要有返回地址以及使用的寄存器信息,這就是在本文開頭講解的寄存器,我們將其稱為函數(shù)運(yùn)行時(shí)上下文,簡(jiǎn)稱為context。

這些context保存在哪里呢?我想你已經(jīng)猜到了,沒錯(cuò),就是棧中,我們?yōu)槊總€(gè)函數(shù)分配一塊空間,當(dāng)A函數(shù)調(diào)用B函數(shù)時(shí),我們?cè)谶@塊空間中保存該函數(shù)的context,當(dāng)B函數(shù)執(zhí)行結(jié)束后,我們?cè)儆迷揷ontext恢復(fù)A函數(shù)的運(yùn)行。

如果是A函數(shù)調(diào)用B函數(shù),B函數(shù)調(diào)用C函數(shù)的話,那么:

這塊用來(lái)保存context的空間就是棧幀,當(dāng)然這里不止保存上下文信息,還保存有函數(shù)參數(shù),局部變量等信息。

從這里我們可以看到,棧+上下文讓我們實(shí)現(xiàn)了函數(shù)調(diào)用。

當(dāng)然限于篇幅,這里關(guān)于函數(shù)運(yùn)行時(shí)棧的講解非常簡(jiǎn)略,關(guān)于這一部分更加詳細(xì)的講解關(guān)注公眾號(hào)碼農(nóng)的荒島求生并回復(fù)關(guān)鍵詞運(yùn)行時(shí)棧即可。

系統(tǒng)調(diào)用與內(nèi)核棧

當(dāng)我們讀寫磁盤文件或者創(chuàng)建新的線程時(shí),你有沒有想過(guò)到底是誰(shuí)幫你讀寫的文件,是誰(shuí)幫你創(chuàng)建的線程呢?

答案是操作系統(tǒng)。

是的,當(dāng)你調(diào)用類似open這樣的函數(shù)時(shí),其實(shí)是操作系統(tǒng)在幫你完成文件打開操作,用戶程序向操作系統(tǒng)請(qǐng)求服務(wù)就是通過(guò)系統(tǒng)調(diào)用實(shí)現(xiàn)的。

好奇的同學(xué)可能會(huì)繼續(xù)問(wèn),既然是操作系統(tǒng)來(lái)完成這些請(qǐng)求,那么操作系統(tǒng)內(nèi)部肯定也是調(diào)用一系列函數(shù)來(lái)完成請(qǐng)求處理,有函數(shù)調(diào)用就需要運(yùn)行時(shí)棧,那么操作系統(tǒng)完成系統(tǒng)調(diào)用所需要的運(yùn)行時(shí)棧在哪里呢?

答案就在內(nèi)核棧中,Kernel Stack。

原來(lái),每一個(gè)用戶態(tài)線程在內(nèi)核態(tài)都有一個(gè)對(duì)應(yīng)的內(nèi)核棧:

當(dāng)用戶線程需要請(qǐng)求操作系統(tǒng)服務(wù)時(shí)利用系統(tǒng)調(diào)用切換到內(nèi)核模式,這時(shí)內(nèi)核開始代表該用戶態(tài)線程執(zhí)行,內(nèi)核的執(zhí)行過(guò)程需要的運(yùn)行時(shí)棧就放在了上圖中的內(nèi)核棧中。

讓我們來(lái)看一下系統(tǒng)調(diào)用的過(guò)程。

開始時(shí),程序運(yùn)行在用戶態(tài),此時(shí)內(nèi)核棧還是空的,假設(shè)用戶態(tài)執(zhí)行到functionD時(shí)需要請(qǐng)求操作系統(tǒng)服務(wù),假設(shè)functionD需要調(diào)用open函數(shù),該函數(shù)內(nèi)部包含就系統(tǒng)調(diào)用,被編譯器翻譯后會(huì)生成一條int指令,此時(shí)CPU執(zhí)行到該指令:

該指令的執(zhí)行將觸發(fā)CPU的狀態(tài)切換,此時(shí)CPU從用戶態(tài)切換為內(nèi)核態(tài),并找到該用戶態(tài)線程對(duì)應(yīng)的內(nèi)核線程,注意重點(diǎn)來(lái)了,此時(shí)用戶態(tài)線程的執(zhí)行上下文信息(寄存器信息)被保存在內(nèi)核棧中:

此后CPU開始在內(nèi)核中執(zhí)行open相關(guān)的操作,后續(xù)內(nèi)核棧會(huì)像用戶態(tài)運(yùn)行時(shí)棧一樣隨著函數(shù)的調(diào)用和返回增長(zhǎng)以及減少:

當(dāng)系統(tǒng)調(diào)用執(zhí)行完成后,根據(jù)內(nèi)核棧中保存的用戶態(tài)程序上下文信息恢復(fù)CPU狀態(tài),并從內(nèi)核態(tài)切換回用戶態(tài),這樣用戶態(tài)線程就可以繼續(xù)運(yùn)行了:

現(xiàn)在你應(yīng)該明白這個(gè)過(guò)程了吧。

那么操作系統(tǒng)為什么要這么麻煩的費(fèi)心維護(hù)用戶態(tài)以及內(nèi)核態(tài)呢?用戶態(tài)程序?yàn)槭裁匆孟到y(tǒng)調(diào)用來(lái)請(qǐng)求操作系統(tǒng)服務(wù)呢?不能直接像普通函數(shù)一樣調(diào)用操作系統(tǒng)的代碼嗎?關(guān)于這些問(wèn)題的答案,你可以參考博主的深入理解操作系統(tǒng)第2章,關(guān)注公眾號(hào)碼農(nóng)的荒島求生并回復(fù)操作系統(tǒng)這幾個(gè)字即可。

中斷與中斷函數(shù)棧

現(xiàn)在我們已經(jīng)講解了兩種涉及CPU上下文切換的場(chǎng)景,包括函數(shù)調(diào)用以及系統(tǒng)調(diào)用,接下來(lái)我們?cè)倏匆环N,中斷處理。

你的計(jì)算機(jī)之所以能接受鍵盤按鍵、鼠標(biāo)指針、網(wǎng)絡(luò)數(shù)據(jù)等,都是通過(guò)中斷機(jī)制來(lái)完成的。

中斷本質(zhì)上就是打斷當(dāng)前CPU的執(zhí)行流,跳轉(zhuǎn)到具體的中斷處理函數(shù)中,當(dāng)中斷處理函數(shù)執(zhí)行完成后再跳轉(zhuǎn)回來(lái)。

既然中斷處理函數(shù)也是函數(shù),那么必然和普通函數(shù)一樣需要運(yùn)行時(shí)棧,那么中斷處理函數(shù)的運(yùn)行時(shí)棧又在哪里呢?

這分為兩種情況:

  • 中斷處理函數(shù)是沒有自己特定的棧的,中斷處理函數(shù)依賴內(nèi)核棧來(lái)完成中斷處理。
  • 中斷處理函數(shù)有自己特定的棧,被稱之為ISR棧,ISR是interrupt service routine的簡(jiǎn)寫,即中斷處理函數(shù)棧。由于處理中斷的是CPU,因此在這種方案下每個(gè)CPU都有一個(gè)自己的中斷處理?xiàng)!?/li>

為了簡(jiǎn)單起見,我們以中斷處理函數(shù)共享內(nèi)核棧為例來(lái)講解。

實(shí)際上你會(huì)發(fā)現(xiàn)中斷處理函數(shù)和系統(tǒng)調(diào)用比較類似,不同的是系統(tǒng)調(diào)用是用戶態(tài)程序主動(dòng)發(fā)起的,而中斷處理是外部設(shè)備發(fā)起的,也就是說(shuō)CPU在執(zhí)行完用戶態(tài)的任何一條指令后都可能因?yàn)橹袛喈a(chǎn)生而暫停當(dāng)前程序的執(zhí)行轉(zhuǎn)而去執(zhí)行中斷處理函數(shù),如圖所示:

此后的故事和系統(tǒng)調(diào)用類似,CPU從用戶態(tài)切換為內(nèi)核態(tài),并找到該用戶態(tài)線程對(duì)應(yīng)的內(nèi)核線程,并將用戶態(tài)線程的執(zhí)行上下文信息保存在內(nèi)核棧中:

此后CPU跳轉(zhuǎn)到中斷處理函數(shù)起始地址,中斷處理函數(shù)在運(yùn)行過(guò)程中內(nèi)核棧會(huì)像用戶態(tài)運(yùn)行時(shí)棧一樣隨著函數(shù)的調(diào)用和返回增長(zhǎng)以及減少:

當(dāng)中斷處理函數(shù)執(zhí)行完成后,根據(jù)內(nèi)核棧中保存的用戶態(tài)程序上下文信息恢復(fù)CPU狀態(tài),并從內(nèi)核態(tài)切換回用戶態(tài),這樣用戶態(tài)線程就可以繼續(xù)運(yùn)行了。

每一次你敲擊鍵盤、滑動(dòng)鼠標(biāo)、下載文件等都會(huì)有一次上述過(guò)程。關(guān)于中斷處理更加完整的闡述參見博主深入理解操作系統(tǒng)第3章,關(guān)注公眾號(hào)碼農(nóng)的荒島求生并回復(fù)操作系統(tǒng)即可。

既然你已經(jīng)知道了中斷是如何實(shí)現(xiàn)的,接下來(lái)讓我們看下最有意思的線程切換是如何實(shí)現(xiàn)的。

線程切換與內(nèi)核棧

現(xiàn)在我們知道了每個(gè)線程除了用戶態(tài)的函數(shù)運(yùn)行時(shí)棧之外還有一個(gè)我們看不見的內(nèi)核棧,系統(tǒng)調(diào)用陷入內(nèi)核后,開始將用戶態(tài)上下文信息保存在相應(yīng)的內(nèi)核棧上,此后內(nèi)核代表該線程在內(nèi)核中執(zhí)行相應(yīng)的操作,執(zhí)行結(jié)束后根據(jù)內(nèi)核棧上保存的上下文信息恢復(fù)用戶態(tài)線程。

那么線程切換是如何實(shí)現(xiàn)的呢?線程切換是如何給CPU實(shí)施換顱術(shù)的呢?

本文剩余部分已收錄至小風(fēng)哥的深入理解操作系統(tǒng)第五章第四節(jié),關(guān)注公眾號(hào)碼農(nóng)的荒島求生并回復(fù)操作系統(tǒng)即可。

總結(jié)

程序的運(yùn)行狀態(tài)說(shuō)到底就是CPU內(nèi)部的一些寄存器信息,比如指向運(yùn)行時(shí)棧頂?shù)臈<拇嫫鳌⒅赶蛳乱粭l要執(zhí)行指令的PC寄存器等,這些被稱為上下文信息,能得到這些信息你就能給暫停或者回復(fù)程序的運(yùn)行。

上下文信息的保存與恢復(fù)通常通過(guò)棧這種機(jī)制來(lái)實(shí)現(xiàn),棧FILO的特性天然適合應(yīng)對(duì)該場(chǎng)景,這也使得棧成為計(jì)算機(jī)系統(tǒng)中最為重要的數(shù)據(jù)結(jié)構(gòu)之一。

上下文信息+棧的組合使得函數(shù)調(diào)用、系統(tǒng)調(diào)用、進(jìn)程切換、線程切換以及中斷處理成為可能。

我是小風(fēng)哥,希望這篇文章對(duì)大家理解CPU以及程序運(yùn)行有所幫助。

本文轉(zhuǎn)載自微信公眾號(hào)「碼農(nóng)的荒島求生」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系碼農(nóng)的荒島求生公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 碼農(nóng)的荒島求生
相關(guān)推薦

2018-07-12 13:15:06

2021-05-10 08:20:32

CPU 符號(hào)整數(shù)

2018-12-06 12:58:50

CPU內(nèi)存模塊

2019-07-10 05:08:05

CPU內(nèi)存分頁(yè)管理

2017-01-12 15:17:27

線程CPU定位

2010-07-05 15:37:01

SQL Server

2021-04-08 09:32:17

鴻蒙HarmonyOS應(yīng)用

2021-06-24 08:02:35

線程池Java代碼

2010-03-18 16:02:09

python 多線程

2023-03-05 22:30:25

JavaCPU

2024-10-11 16:57:18

2025-04-24 08:15:00

Redis單線程線程

2020-11-10 08:41:51

CPU執(zhí)行任務(wù)內(nèi)存

2021-11-10 09:15:00

CPU01 二進(jìn)制Linux

2018-08-16 11:30:12

JavaCPU緩存

2019-08-16 14:18:38

CPU故障

2019-01-28 08:50:09

線程安全

2024-05-20 13:13:01

線程安全Java

2018-03-13 09:34:36

Kubernetes容器系統(tǒng)

2022-03-29 16:10:45

WindowsLinux操作系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日日干日日操 | 国产亚洲精品久久久久动 | 91私密视频| 在线中文字幕av | 日本高清在线一区 | 最新av片 | 91精品国产综合久久久久久丝袜 | 国产做a爱片久久毛片 | 国产乱码精品一区二区三区五月婷 | 国产原创视频 | 一级毛片在线视频 | 日日爱视频 | www.夜夜骑.com | 7777在线 | 一区二区播放 | 日本理论片好看理论片 | 亚洲精品乱码8久久久久久日本 | 欧美日韩国产在线 | 亚洲国产精品视频一区 | 免费观看av网站 | 每日更新av | 一区二区三区视频在线观看 | 久久精品在线播放 | 成人久久久 | 久久久久久中文字幕 | 中文字幕亚洲欧美 | 看黄在线 | 日本三级网址 | 国产一区久久精品 | 久久精品国产99国产精品 | 中文字幕1区2区3区 日韩在线视频免费观看 | 夜久久| 黄色三级免费 | 精品中文字幕视频 | 久久久久久久综合色一本 | 国产免费av在线 | 国产一区二 | 亚洲欧美一区二区三区1000 | 国产欧美日韩精品一区二区三区 | 久久久久国产精品免费免费搜索 | 欧美精品乱码99久久影院 |