<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          啥叫進(jìn)入內(nèi)核態(tài)???

          共 5967字,需瀏覽 12分鐘

           ·

          2022-02-12 15:48

          作者:靈劍
          鏈接:https://www.zhihu.com/question/306127044/answer/555327651

          對操作系統(tǒng)有過了解的童鞋都知道內(nèi)核態(tài),而且大家或多或少都聽過進(jìn)入內(nèi)核態(tài),這到底是是啥意思呢?這篇文章就詳細(xì)給大家科普下。

          建議首先先集中力量在計(jì)算機(jī)組成原理上,不過的確單看計(jì)算機(jī)組成原理也比較枯燥,可以結(jié)合起來稍微講一下。

          太長不看的提前總結(jié):

          1. 內(nèi)核態(tài),或者說 CPU 的特權(quán)模式,是 CPU 的一種工作狀態(tài),它影響 CPU 對不同指令的執(zhí)行結(jié)果。操作系統(tǒng)通過跟 CPU 配合,設(shè)置特權(quán)模式和用戶模式,來防止應(yīng)用程序進(jìn)行越權(quán)的操作。
          2. 防止應(yīng)用程序越權(quán)訪問內(nèi)存時(shí)使用了虛擬地址空間映射的技術(shù),這是操作系統(tǒng)軟件配合硬件的 MMU 共同實(shí)現(xiàn)的。在用戶模式下,應(yīng)用程序訪問的內(nèi)存地址是虛擬內(nèi)存地址,會(huì)映射到操作系統(tǒng)指定的物理地址上。這個(gè)虛擬內(nèi)存地址空間就是你說的用戶空間。
          3. 內(nèi)核態(tài)是個(gè)操作系統(tǒng)概念,雖然對應(yīng)到 CPU 的特權(quán)模式,但一般如果沒有操作系統(tǒng),就不說內(nèi)核態(tài)了,直接說運(yùn)行在 CPU 的特權(quán)模式應(yīng)該沒毛病。
          4. 應(yīng)用程序無法自由進(jìn)入內(nèi)核態(tài),只能通過操作系統(tǒng)提供的接口調(diào)用進(jìn)入,或者在硬件中斷到來時(shí)被動(dòng)進(jìn)入。
          5. 應(yīng)用程序通過操作系統(tǒng)功能來使用硬件。

          首先從問題最關(guān)鍵的地方開始:歸根到底為什么需要保護(hù)模式?

          從計(jì)算機(jī)組成原理的最基礎(chǔ)的理論開始講起。說到計(jì)算機(jī),從馮諾依曼體系講起,最重要的就是五部分:運(yùn)算器、控制器、存儲(chǔ)器、輸入設(shè)備、輸出設(shè)備。

          其中,運(yùn)算器是無狀態(tài)的;控制器配合一部分寄存器,但是寄存器數(shù)量很少,而且通常都很容易被修改;輸入設(shè)備、輸出設(shè)備只有接受指令的時(shí)候才動(dòng)作。歸根結(jié)底來說,整個(gè)計(jì)算機(jī)的運(yùn)行狀態(tài)幾乎完全由存儲(chǔ)器和少數(shù)幾個(gè)寄存器控制。

          也就是說,如果一段程序能夠完全控制物理內(nèi)存,那么它就能做到任意改變計(jì)算機(jī)的狀態(tài),包括干掉整個(gè)操作系統(tǒng)然后把自己變成操作系統(tǒng);把自己變成操作系統(tǒng)的一部分等等。通常來說操作系統(tǒng)肯定是不樂意的了。

          早期的 DOS 這樣的操作系統(tǒng),運(yùn)行在實(shí)模式上,就遇到的是這樣的情況:它其實(shí)將要執(zhí)行的應(yīng)用程序加載變成了操作系統(tǒng)的一部分,然后混合起來運(yùn)行,哪一段是用戶程序、哪一段是操作系統(tǒng)并沒有很明確的界限:用戶程序退出就回到操作系統(tǒng);用戶程序觸發(fā)軟中斷就到操作系統(tǒng),返回又回到用戶程序;用戶程序自己可以訪問大部分的硬件設(shè)備;用戶程序甚至可以隨意修改屬于操作系統(tǒng)的數(shù)據(jù)。于是,當(dāng)時(shí)的許多病毒也毫不客氣地把自己直接連接到了操作系統(tǒng)的程序里面,一旦執(zhí)行就永遠(yuǎn)駐留成為操作系統(tǒng)的一部分。當(dāng)時(shí)在 DOS 上流行的病毒可謂多種多樣、五花八門。

          單任務(wù)的情況下已經(jīng)有不少問題了,到了多任務(wù)模式下,問題就更嚴(yán)重了:

          1. 因?yàn)槎鄠€(gè)應(yīng)用程序要獨(dú)立加載,如果兩個(gè)應(yīng)用程序執(zhí)意要使用同一個(gè)內(nèi)存地址,那就會(huì)發(fā)生嚴(yán)重的問題,操作系統(tǒng)必須防止這種事情發(fā)生
          2. 外部設(shè)備一般來說都是很傻的,它并不知道多任務(wù)的存在,不管誰操作外部設(shè)備它都是一樣響應(yīng)。這樣如果多個(gè)應(yīng)用程序自己直接去操縱硬件設(shè)備,就會(huì)出現(xiàn)相互沖突,有可能一個(gè)程序的數(shù)據(jù)被發(fā)送到了另一個(gè)程序等等
          3. 操作系統(tǒng)必須自己響應(yīng)硬件中斷,通過硬件中斷來切換任務(wù)上下文,讓合適的任務(wù)在合適的時(shí)機(jī)繼續(xù)執(zhí)行。如果應(yīng)用程序自己把中斷響應(yīng)程序改掉了,整個(gè)操作系統(tǒng)都會(huì)崩潰
          4. 操作系統(tǒng)必須有能力在單個(gè)應(yīng)用程序崩潰的情況下清理這個(gè)應(yīng)用程序使用的資源,保證不影響其他應(yīng)用程序;這就要求它必須清楚知道每個(gè)應(yīng)用程序使用了哪些資源

          這還只是考慮到應(yīng)用程序都是善良的情況下,要對付惡意程序就需要更強(qiáng)的手段。

          可我們前面說了,物理內(nèi)存就是整個(gè)計(jì)算機(jī)狀態(tài)的全部,如果程序有辦法讀寫所有的物理內(nèi)存和寄存器,那任何保護(hù)手段都無濟(jì)于事。所以要限制應(yīng)用程序的行為,必須在應(yīng)用程序和操作系統(tǒng)執(zhí)行時(shí)有不同的狀態(tài),核心問題在于保護(hù)關(guān)鍵寄存器和重要的物理內(nèi)存。

          這個(gè)目標(biāo)顯然是必須要硬件配合的,否則 CPU 如何區(qū)分當(dāng)前究竟是執(zhí)行操作系統(tǒng)(開放所有能力)還是應(yīng)用程序(限制危險(xiǎn)功能)呢?那么我們?nèi)绻豢紤]實(shí)際結(jié)果,只從需求上面分析如何解決這個(gè)問題,應(yīng)該可以得到以下結(jié)論:

          1. CPU 必須至少有兩種不同的狀態(tài):操作系統(tǒng)狀態(tài)和應(yīng)用程序狀態(tài)。不同狀態(tài)下,相同指令會(huì)產(chǎn)生不同的結(jié)果,也就保證某些任務(wù)只有操作系統(tǒng)能執(zhí)行,某些只有應(yīng)用程序能執(zhí)行。
          2. 操作系統(tǒng)必須有辦法配合 CPU,設(shè)置哪些內(nèi)存可以訪問,哪些內(nèi)存不能訪問(或者說只有操作系統(tǒng)狀態(tài)下能訪問),不能訪問的包括操作系統(tǒng)自己的代碼區(qū)和數(shù)據(jù)區(qū)、中斷向量表等。
          3. 應(yīng)用程序狀態(tài)下不能直接訪問硬件設(shè)備
          4. CPU 在觸發(fā)中斷時(shí)需要自動(dòng)切換到操作系統(tǒng)狀態(tài)(否則無法進(jìn)行多任務(wù)切換)
          5. 操作系統(tǒng)狀態(tài)可以自由切換到應(yīng)用程序狀態(tài);應(yīng)用程序狀態(tài)不能任意切換到操作系統(tǒng)狀態(tài),但也需要有觸發(fā)進(jìn)入操作系統(tǒng)代碼并切換到操作系統(tǒng)狀態(tài)的能力(否則無法調(diào)用操作系統(tǒng)功能)

          現(xiàn)在我們回到實(shí)際 CPU 的設(shè)計(jì)上,顯然實(shí)際 CPU 的設(shè)計(jì)者的思路跟我們是差不多的。這里我們叫做操作系統(tǒng)狀態(tài)的,在實(shí)際操作系統(tǒng)概念中就叫做內(nèi)核態(tài),在 CPU 設(shè)計(jì)上則叫做特權(quán)模式;我們叫做應(yīng)用程序狀態(tài)的,在實(shí)際操作系統(tǒng)概念中叫做用戶態(tài),CPU 設(shè)計(jì)上叫做用戶模式。

          注意到,內(nèi)核態(tài)并不是一個(gè)東西,沒有處于什么地方一說,它是 CPU 的兩種狀態(tài)之一。如果不是說進(jìn)入內(nèi)核態(tài),而是說切換到內(nèi)核態(tài),可能你就沒有這種誤解了。都怪intel將系統(tǒng)調(diào)用的指令起名字叫sysenter,所以大家都比較習(xí)慣說“進(jìn)入”內(nèi)核態(tài)。

          實(shí)際上 CPU 可能被細(xì)分為更多的運(yùn)行模式,而不僅僅是特權(quán)和用戶兩種模式,不過操作系統(tǒng)至少需要這兩種。有的時(shí)候特權(quán)和用戶模式也指的并不是一種真正的模式,而是一類模式,比如好幾種類似的但略有區(qū)別的運(yùn)行模式都合成特權(quán)模式之類。

          這種特權(quán) + 用戶的多模式切換的運(yùn)行方式,就叫做(x86)CPU 的保護(hù)模式功能。保護(hù)模式之所以也是一個(gè)模式,有一定的歷史原因,因?yàn)?intel CPU 每一代產(chǎn)品都會(huì)盡量兼容之前的產(chǎn)品,早期的 CPU 啟動(dòng)時(shí)是實(shí)模式,沒有這種模式切換的功能,后來的 CPU 為了兼容早期的 CPU,啟動(dòng)時(shí)也處于實(shí)模式,需要引導(dǎo)程序主動(dòng)進(jìn)入保護(hù)模式,然后才擁有多模式切換的能力。這些是歷史原因和一些細(xì)節(jié)問題。

          對于 CPU 本身來說,CPU 是不知道究竟哪一段代碼屬于應(yīng)用程序、哪一段代碼屬于操作系統(tǒng)的,它沒有能力識(shí)別當(dāng)前執(zhí)行的代碼究竟應(yīng)不應(yīng)該有權(quán)限,因此它只負(fù)責(zé)按照程序邏輯來執(zhí)行:如果指令自己要求自己進(jìn)入用戶模式,CPU 就進(jìn)入用戶模式,但進(jìn)去之后,就只有特定的方法才能再回到特權(quán)模式。所以并不是說進(jìn)入特權(quán)模式就一定是操作系統(tǒng)代碼了,CPU 并沒有這個(gè)保證。但是,我們說了,保護(hù)模式設(shè)計(jì)的目標(biāo)就是為了讓應(yīng)用程序代碼受到限制,如果應(yīng)用程序的代碼進(jìn)入了特權(quán)模式,這個(gè)限制就完全失效了,所以操作系統(tǒng)設(shè)計(jì)上會(huì)使用各種各樣的巧妙手段,配合CPU的功能,保障應(yīng)用程序只能通過跳轉(zhuǎn)到操作系統(tǒng)代碼的方式來切換到內(nèi)核態(tài)上,這樣也就間接保障了內(nèi)核態(tài)下執(zhí)行的都是操作系統(tǒng)(包括驅(qū)動(dòng))的代碼。

          接下來我們討論如何限制內(nèi)存訪問的問題,這也是這個(gè)設(shè)計(jì)中最困難的一部分。相比來說,在用戶模式下禁用一部分指令功能比較簡單,無非是控制器里加入相應(yīng)的組合邏輯,判斷當(dāng)前狀態(tài),如果狀態(tài)為用戶模式則拒絕執(zhí)行特權(quán)指令而已。而內(nèi)存讀寫則不一樣,指令是相同的,只是訪問的內(nèi)存地址不同,這時(shí)候有些地址是可以訪問的,有些地址則不能訪問,能不能訪問的區(qū)別僅僅在內(nèi)存地址上。要知道,CPU 是支持利用寄存器間接尋址的,因此這個(gè)非法的指令不可能在譯碼的階段就發(fā)現(xiàn),而是必須在執(zhí)行期間發(fā)現(xiàn);同時(shí),哪些地址可以訪問,哪些地址不能訪問,必須完全是可配置的,操作系統(tǒng)有極大的自由。最后,這個(gè)系統(tǒng)還必須對應(yīng)用程序有最基礎(chǔ)的友好性,不能讓應(yīng)用程序太難寫。

          既然內(nèi)存里每一個(gè)單元是否允許訪問都需要能夠設(shè)置,而內(nèi)存的大小是不確定的,那這個(gè)設(shè)置的數(shù)量也不確定,而且會(huì)較為龐大,在寸土寸金(?)的 CPU 里放這么多、這么復(fù)雜的設(shè)置是很不合適的,唯一可行的方案就是通過內(nèi)存自己來管理內(nèi)存——使用一部分內(nèi)存用來存儲(chǔ)其他內(nèi)存應(yīng)該如何使用的配置。這樣,實(shí)際訪問內(nèi)存時(shí),就需要——

          先訪問內(nèi)存中的內(nèi)存配置,根據(jù)內(nèi)存配置判斷要訪問的內(nèi)存是否允許訪問,如果不允許訪問需要觸發(fā)非法操作的中斷,而如果允許訪問則正常訪問;同時(shí),內(nèi)存中的內(nèi)存配置也是內(nèi)存的一部分,所以內(nèi)存中的內(nèi)存配置也會(huì)受到內(nèi)存中的內(nèi)存配置的管理。

          僅僅從這個(gè)拗口程度上也能知道這是一件多么復(fù)雜的事情,使用內(nèi)存自己來管理內(nèi)存,這就好比左腳踩著右腳上天梯,一個(gè)不小心玩脫了就出大事了。而且為了讓帶配置的內(nèi)存使用起來有效率,還需要大量使用緩存技術(shù)。

          CPU 中引入了一種稱為 MMU 的單元,它可能是現(xiàn)代 CPU 最復(fù)雜的組件之一了。它能從內(nèi)存中以指定格式加載配置,從而影響用戶模式下訪問內(nèi)存的特性。為了方便進(jìn)程切換,這個(gè)格式往往有復(fù)雜的數(shù)據(jù)結(jié)構(gòu),還要支持多種多樣的配置功能。在用戶模式下,所有內(nèi)存訪問經(jīng)過 MMU,從而對內(nèi)存的訪問受到了保護(hù);在特權(quán)模式下,內(nèi)存訪問繞過 MMU,直接訪問物理內(nèi)存,從而獲得完整的權(quán)限。

          從具體設(shè)計(jì)上來說,最直接的想法就是用戶模式和特權(quán)模式都使用相同的內(nèi)存地址,只是在用戶模式下設(shè)置哪些內(nèi)存可訪問,哪些不可訪問。這種方法是否可行呢?實(shí)際上是可行的,不過略有一些缺陷:

          1. 在保護(hù)模式出現(xiàn)之前,編譯器都是針對實(shí)模式設(shè)計(jì)的,在編譯過程中,使用哪些內(nèi)存地址范圍、內(nèi)存的什么位置放什么數(shù)據(jù),都完全是編譯器可以自己決定的。即使是保護(hù)模式出現(xiàn)之后,操作系統(tǒng)的部分也需要相同的編譯方式。如果應(yīng)用程序的編譯需要放棄這一套邏輯,改成所有地址都由操作系統(tǒng)分配,那現(xiàn)有的匯編程序和編譯器都需要重寫,這個(gè)代價(jià)難以接受。
          2. 應(yīng)用程序經(jīng)常會(huì)需要使用一大片連續(xù)的內(nèi)存空間,比如說涉及數(shù)組的一系列算法。如果內(nèi)存空間全部都是動(dòng)態(tài)分配的,那有些程序可能會(huì)不斷地申請小塊小塊的空間,從而讓內(nèi)存空間碎片化,沒有連續(xù)成片的內(nèi)存。等這些程序退出之后,釋放出來的內(nèi)存都是小塊、不連續(xù)的,操作系統(tǒng)就沒法讓其他應(yīng)用程序使用連續(xù)成片的內(nèi)存了。
          3. 安全上有隱患,雖然應(yīng)用程序沒法讀取其他內(nèi)存,但是應(yīng)用程序可以知道哪些內(nèi)存已經(jīng)被其他應(yīng)用程序用了,于是可以從內(nèi)存地址的分配上分析出一些信息,例如當(dāng)前操作系統(tǒng)可能執(zhí)行了哪些其他應(yīng)用程序,這些應(yīng)用程序可能處于什么狀態(tài)等等。還有可能因?yàn)?CPU 實(shí)現(xiàn)的 bug 導(dǎo)致應(yīng)用程序能以意想不到的方式讀取到不應(yīng)當(dāng)能讀取的數(shù)據(jù)。
          4. 現(xiàn)代操作系統(tǒng)希望支持一些高級的內(nèi)存管理方式,例如虛擬內(nèi)存——將一部分不使用的內(nèi)存暫時(shí)放在磁盤上,這樣可以用較少的內(nèi)存支撐更多的應(yīng)用程序;寫時(shí)復(fù)制——兩個(gè)應(yīng)用程序使用相同的內(nèi)存塊,希望能暫時(shí)使用同一個(gè)物理內(nèi)存地址,但是其中一個(gè)需要修改的時(shí)候再將它復(fù)制成兩份獨(dú)立的內(nèi)存塊,從而節(jié)約內(nèi)存。

          現(xiàn)代 MMU 通常使用虛擬地址空間的技術(shù)來解決這個(gè)問題,也就是你說的“用戶空間”。在用戶模式下,所有訪問內(nèi)存的地址實(shí)際上都是虛擬地址,它與實(shí)際的物理地址是對應(yīng)不上的。這樣,即便兩個(gè)應(yīng)用程序使用了相同的地址,它們也可以做到互不干擾,只需要通過技術(shù)手段讓它們實(shí)際映射到不同的物理地址就行了。MMU和操作系統(tǒng)通過稱作頁表的數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)虛擬地址到物理地址的映射,一般來說在x86-64系統(tǒng)中,內(nèi)存按照4KB的大小分成頁,每個(gè)地址對齊的頁可以獨(dú)立從任意一個(gè)虛擬地址段,映射到任意一個(gè)物理內(nèi)存地址段,兩個(gè)起始地址的低12位都是0(也就是所謂地址對齊,這樣任意一個(gè)虛擬地址映射到物理地址時(shí),最低12位不需要?jiǎng)樱?。頁表的結(jié)構(gòu)在每次進(jìn)入用戶模式之前都可以重新設(shè)置,這樣切換進(jìn)程之后,頁表發(fā)生了變化,同一個(gè)虛擬地址就會(huì)映射到不同的物理地址上,這就同時(shí)實(shí)現(xiàn)了多個(gè)目標(biāo):

          1. 應(yīng)用程序有獨(dú)立的虛擬地址空間
          2. 應(yīng)用程序只能訪問已經(jīng)映射了的虛擬地址空間,未映射的物理地址無法訪問(實(shí)現(xiàn)了保護(hù)內(nèi)存)
          3. 頁表和中斷向量表,理所當(dāng)然不會(huì)被映射出來
          4. 部分RISC(x86是 CISC)的架構(gòu)上,內(nèi)存和外部設(shè)備有統(tǒng)一的地址空間,不映射外設(shè)的地址,也就阻止了對外設(shè)的訪問
          5. 應(yīng)用程序看來連續(xù)的內(nèi)存,在物理內(nèi)存上不需要是連續(xù)的,內(nèi)存使用的效率很高
          6. 以某些方式訪問某些頁面時(shí)可以觸發(fā)操作系統(tǒng)的中斷,操作系統(tǒng)可以趁這個(gè)機(jī)會(huì)修改頁表,這就給操作系統(tǒng)實(shí)現(xiàn)高級內(nèi)存管理功能打下了基礎(chǔ)

          最后我們來說一下應(yīng)用程序怎么訪問外部設(shè)備的問題。我們說了,用戶模式下應(yīng)用程序無法直接訪問硬件設(shè)備,但如果完全沒法利用硬件設(shè)備,那就太不方便了。這兩者的權(quán)衡是,應(yīng)用程序通過操作系統(tǒng)使用硬件,也就是說應(yīng)用程序給操作系統(tǒng)發(fā)起請求,操作系統(tǒng)處理請求時(shí)將請求轉(zhuǎn)發(fā)到硬件,硬件響應(yīng)后,再將請求轉(zhuǎn)發(fā)回應(yīng)用程序。

          許多硬件使用中斷和 DMA 來傳輸信號或數(shù)據(jù)。這種情況下,操作系統(tǒng)開始操作后,到硬件操作完成前會(huì)有一段空閑時(shí)間,這時(shí)候操作系統(tǒng)可以將當(dāng)前應(yīng)用程序掛起,先去執(zhí)行其他的應(yīng)用程序。當(dāng)硬件操作完成時(shí),會(huì)觸發(fā)中斷,中斷向量表在內(nèi)存中,是操作系統(tǒng)提前設(shè)置好的,指向了操作系統(tǒng)自己的代碼;同時(shí),這個(gè)中斷也會(huì)立即強(qiáng)迫 CPU 進(jìn)入特權(quán)模式。這時(shí)候操作系統(tǒng)就有機(jī)會(huì)來處理硬件返回的數(shù)據(jù)了,同時(shí)根據(jù)進(jìn)程優(yōu)先級,可以將之前掛起的進(jìn)程重新切換回來重新開始繼續(xù)執(zhí)行。

          不同硬件往往有不同的接口,但操作系統(tǒng)會(huì)希望提供給應(yīng)用程序統(tǒng)一的接口,這中間就涉及到驅(qū)動(dòng)適配的問題,廠家的驅(qū)動(dòng)程序可以將通用的請求轉(zhuǎn)化為自己家硬件能識(shí)別的請求格式。

          保護(hù)模式不意味著應(yīng)用程序訪問硬件的能力變?nèi)趿?,?shí)際上,應(yīng)用程序訪問硬件的能力完全取決于操作系統(tǒng)是否允許。別說是 Windows PE,實(shí)際上任意版本的 Windows 都是可以允許一個(gè)最高權(quán)限的用戶程序直接讀寫物理硬盤的(通過 CreateFileEx 的 Windows API 就可以,就跟打開一個(gè)普通文件一樣),唯一的問題在于 Windows 依賴很多磁盤文件,如果在普通 Windows 執(zhí)行過程中格式化系統(tǒng)盤,操作系統(tǒng)會(huì)崩潰,而 Windows PE 比較小,可以將重要的東西都整個(gè)加載到內(nèi)存里,就可以在保持操作系統(tǒng)正常工作的情況下格式化硬盤了。






          ?往期推薦?

          ??

          用了這么久 Linux ,才知道這些概念。。。

          哈哈哈,去年這些網(wǎng)站"崩了"!

          從零到阿里的三年

          中美教育對比

          原來這才是動(dòng)態(tài)代理?。?!

          原來這才是 Socket!

          "我的"職業(yè)規(guī)劃

          手撕匯編。。。


          瀏覽 50
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天爽天天爽夜夜爽毛片资源 | 亚洲夜福利 | 欧美 级毛片 | 韩国一区二区三区免费视频 | 成人无码A级毛片 |