1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        操作系統(tǒng)常用知識(shí)總結(jié)!

        共 27254字,需瀏覽 55分鐘

         ·

        2021-08-24 00:45

        前言

        文章已經(jīng)同步到個(gè)人網(wǎng)站:http://xiaoflyfish.cn/!

        下一篇分享網(wǎng)站基礎(chǔ)!

        「文章較長(zhǎng),可以點(diǎn)贊在看」

        計(jì)算機(jī)結(jié)構(gòu)

        現(xiàn)代計(jì)算機(jī)模型是基于-「馮諾依曼計(jì)算機(jī)模型」

        計(jì)算機(jī)在運(yùn)行時(shí),先從內(nèi)存中取出第一條指令,通過(guò)控制器的譯碼,按指令的要求,從存儲(chǔ)器中取出數(shù)據(jù)進(jìn)行指定的運(yùn)算和邏輯操作等加工,然后再按地址把結(jié)果送到內(nèi)存中去,接下來(lái),再取出第二條指令,在控制器的指揮下完成規(guī)定操作,依此進(jìn)行下去。直至遇到停止指令

        程序與數(shù)據(jù)一樣存貯,按程序編排的順序,一步一步地取出指令,自動(dòng)地完成指令規(guī)定的操作是計(jì)算機(jī)最基本的工作模型

        「計(jì)算機(jī)五大核心組成部分」

        控制器:是整個(gè)計(jì)算機(jī)的中樞神經(jīng),其功能是對(duì)程序規(guī)定的控制信息進(jìn)行解釋,根據(jù)其要求進(jìn)行控制,調(diào)度程序、數(shù)據(jù)、地址,協(xié)調(diào)計(jì)算機(jī)各部分工作及內(nèi)存與外設(shè)的訪問(wèn)等。

        運(yùn)算器:運(yùn)算器的功能是對(duì)數(shù)據(jù)進(jìn)行各種算術(shù)運(yùn)算和邏輯運(yùn)算,即對(duì)數(shù)據(jù)進(jìn)行加工處理。

        存儲(chǔ)器:存儲(chǔ)器的功能是存儲(chǔ)程序、數(shù)據(jù)和各種信號(hào)、命令等信息,并在需要時(shí)提供這些信息。

        輸入:輸入設(shè)備是計(jì)算機(jī)的重要組成部分,輸入設(shè)備與輸出設(shè)備合你為外部設(shè)備,簡(jiǎn)稱外設(shè),輸入設(shè)備的作用是將程序、原始數(shù)據(jù)、文字、字符、控制命令或現(xiàn)場(chǎng)采集的數(shù)據(jù)等信息輸入到計(jì)算機(jī)。

        ?

        常見的輸入設(shè)備有鍵盤、鼠標(biāo)器、光電輸入機(jī)、磁帶機(jī)、磁盤機(jī)、光盤機(jī)等。

        ?

        輸出:輸出設(shè)備與輸入設(shè)備同樣是計(jì)算機(jī)的重要組成部分,它把外算機(jī)的中間結(jié)果或最后結(jié)果、機(jī)內(nèi)的各種數(shù)據(jù)符號(hào)及文字或各種控制信號(hào)等信息輸出出來(lái),微機(jī)常用的輸出設(shè)備有顯示終端CRT、打印機(jī)、激光印字機(jī)、繪圖儀及磁帶、光盤機(jī)等。

        「計(jì)算機(jī)結(jié)構(gòu)分成以下 5 個(gè)部分:」

        輸入設(shè)備;輸出設(shè)備;內(nèi)存;中央處理器;總線。

        內(nèi)存

        在馮諾依曼模型中,程序和數(shù)據(jù)被存儲(chǔ)在一個(gè)被稱作內(nèi)存的線性排列存儲(chǔ)區(qū)域。

        存儲(chǔ)的數(shù)據(jù)單位是一個(gè)二進(jìn)制位,英文是 bit,最小的存儲(chǔ)單位叫作字節(jié),也就是 8 位,英文是 byte,每一個(gè)字節(jié)都對(duì)應(yīng)一個(gè)內(nèi)存地址。

        內(nèi)存地址由 0 開始編號(hào),比如第 1 個(gè)地址是 0,第 2 個(gè)地址是 1, 然后自增排列,最后一個(gè)地址是內(nèi)存中的字節(jié)數(shù)減 1。

        我們通常說(shuō)的內(nèi)存都是隨機(jī)存取器,也就是讀取任何一個(gè)地址數(shù)據(jù)的速度是一樣的,寫入任何一個(gè)地址數(shù)據(jù)的速度也是一樣的。

        CPU

        馮諾依曼模型中 CPU 負(fù)責(zé)控制和計(jì)算,為了方便計(jì)算較大的數(shù)值,CPU 每次可以計(jì)算多個(gè)字節(jié)的數(shù)據(jù)。

        • 如果 CPU 每次可以計(jì)算 4 個(gè) byte,那么我們稱作 32 位 CPU;

        • 如果 CPU 每次可以計(jì)算 8 個(gè) byte,那么我們稱作 64 位 CPU。

        這里的 32 和 64,稱作 CPU 的位寬。

        「為什么 CPU 要這樣設(shè)計(jì)呢?」

        因?yàn)橐粋€(gè) byte 最大的表示范圍就是 0~255。

        比如要計(jì)算 20000*50,就超出了byte 最大的表示范圍了。

        因此,CPU 需要支持多個(gè) byte 一起計(jì)算,當(dāng)然,CPU 位數(shù)越大,可以計(jì)算的數(shù)值就越大,但是在現(xiàn)實(shí)生活中不一定需要計(jì)算這么大的數(shù)值,比如說(shuō) 32 位 CPU 能計(jì)算的最大整數(shù)是 4294967295,這已經(jīng)非常大了。

        「控制單元和邏輯運(yùn)算單元」

        CPU 中有一個(gè)控制單元專門負(fù)責(zé)控制 CPU 工作;還有邏輯運(yùn)算單元專門負(fù)責(zé)計(jì)算。

        「寄存器」

        CPU 要進(jìn)行計(jì)算,比如最簡(jiǎn)單的加和兩個(gè)數(shù)字時(shí),因?yàn)?CPU 離內(nèi)存太遠(yuǎn),所以需要一種離自己近的存儲(chǔ)來(lái)存儲(chǔ)將要被計(jì)算的數(shù)字。

        這種存儲(chǔ)就是寄存器,寄存器就在 CPU 里,控制單元和邏輯運(yùn)算單元非常近,因此速度很快。

        常見的寄存器種類:

        • 通用寄存器,用來(lái)存放需要進(jìn)行運(yùn)算的數(shù)據(jù),比如需要進(jìn)行加和運(yùn)算的兩個(gè)數(shù)據(jù)。
        • 程序計(jì)數(shù)器,用來(lái)存儲(chǔ) CPU 要執(zhí)行下一條指令所在的內(nèi)存地址,注意不是存儲(chǔ)了下一條要執(zhí)行的指令,此時(shí)指令還在內(nèi)存中,程序計(jì)數(shù)器只是存儲(chǔ)了下一條指令的地址。
        • 指令寄存器,用來(lái)存放程序計(jì)數(shù)器指向的指令,也就是指令本身,指令被執(zhí)行完成之前,指令都存儲(chǔ)在這里。

        多級(jí)緩存

        現(xiàn)代CPU為了提升執(zhí)行效率,減少CPU與內(nèi)存的交互(交互影響CPU效率),一般在CPU上集成了多級(jí)緩存架構(gòu)

        「CPU緩存」即高速緩沖存儲(chǔ)器,是位于CPU與主內(nèi)存間的一種容量較小但速度很高的存儲(chǔ)器

        由于CPU的速度遠(yuǎn)高于主內(nèi)存,CPU直接從內(nèi)存中存取數(shù)據(jù)要等待一定時(shí)間周期,Cache中保存著CPU剛用過(guò)或循環(huán)使用的一部分?jǐn)?shù)據(jù),當(dāng)CPU再次使用該部分?jǐn)?shù)據(jù)時(shí)可從Cache中直接調(diào)用,減少CPU的等待時(shí)間,提高了系統(tǒng)的效率,具體包括以下幾種:

        「L1-Cache」

        L1- 緩存在 CPU 中,相比寄存器,雖然它的位置距離 CPU 核心更遠(yuǎn),但造價(jià)更低,通常 L1-Cache 大小在幾十 Kb 到幾百 Kb 不等,讀寫速度在 2~4 個(gè) CPU 時(shí)鐘周期。

        「L2-Cache」

        L2- 緩存也在 CPU 中,位置比 L1- 緩存距離 CPU 核心更遠(yuǎn),它的大小比 L1-Cache 更大,具體大小要看 CPU 型號(hào),有 2M 的,也有更小或者更大的,速度在 10~20 個(gè) CPU 周期。

        「L3-Cache」

        L3- 緩存同樣在 CPU 中,位置比 L2- 緩存距離 CPU 核心更遠(yuǎn),大小通常比 L2-Cache 更大,讀寫速度在 20~60 個(gè) CPU 周期。

        L3 緩存大小也是看型號(hào)的,比如 i9 CPU 有 512KB L1 Cache;有 2MB L2 Cache; 有16MB L3 Cache。

        當(dāng) CPU 需要內(nèi)存中某個(gè)數(shù)據(jù)的時(shí)候,如果寄存器中有這個(gè)數(shù)據(jù),我們可以直接使用;如果寄存器中沒(méi)有這個(gè)數(shù)據(jù),我們就要先查詢 L1 緩存;L1 中沒(méi)有,再查詢 L2 緩存;L2 中沒(méi)有再查詢 L3 緩存;L3 中沒(méi)有,再去內(nèi)存中拿。

        「總結(jié):」

        存儲(chǔ)器存儲(chǔ)空間大小:內(nèi)存>L3>L2>L1>寄存器;

        存儲(chǔ)器速度快慢排序:寄存器>L1>L2>L3>內(nèi)存;

        安全等級(jí)

        「CPU運(yùn)行安全等級(jí)」

        CPU有4個(gè)運(yùn)行級(jí)別,分別為:

        • ring0,ring1,ring2,ring3

        ring0只給操作系統(tǒng)用,ring3誰(shuí)都能用。

        ring0是指CPU的運(yùn)行級(jí)別,是最高級(jí)別,ring1次之,ring2更次之……

        系統(tǒng)(內(nèi)核)的代碼運(yùn)行在最高運(yùn)行級(jí)別ring0上,可以使用特權(quán)指令,控制中斷、修改頁(yè)表、訪問(wèn)設(shè)備等等。

        應(yīng)用程序的代碼運(yùn)行在最低運(yùn)行級(jí)別上ring3上,不能做受控操作。

        如果要做,比如要訪問(wèn)磁盤,寫文件,那就要通過(guò)執(zhí)行系統(tǒng)調(diào)用(函數(shù)),執(zhí)行系統(tǒng)調(diào)用的時(shí)候,CPU的運(yùn)行級(jí)別會(huì)發(fā)生從ring3到ring0的切換,并跳轉(zhuǎn)到系統(tǒng)調(diào)用對(duì)應(yīng)的內(nèi)核代碼位置執(zhí)行,這樣內(nèi)核就為你完成了設(shè)備訪問(wèn),完成之后再?gòu)膔ing0返回ring3。

        這個(gè)過(guò)程也稱作用戶態(tài)和內(nèi)核態(tài)的切換。

        局部性原理

        在CPU訪問(wèn)存儲(chǔ)設(shè)備時(shí),無(wú)論是存取數(shù)據(jù)抑或存取指令,都趨于聚集在一片連續(xù)的區(qū)域中,這就被稱為局部性原理

        「時(shí)間局部性(Temporal Locality):」

        如果一個(gè)信息項(xiàng)正在被訪問(wèn),那么在近期它很可能還會(huì)被再次訪問(wèn)。

        比如循環(huán)、遞歸、方法的反復(fù)調(diào)用等。

        「空間局部性(Spatial Locality):」

        如果一個(gè)存儲(chǔ)器的位置被引用,那么將來(lái)他附近的位置也會(huì)被引用。

        比如順序執(zhí)行的代碼、連續(xù)創(chuàng)建的兩個(gè)對(duì)象、數(shù)組等。

        程序的執(zhí)行過(guò)程

        程序?qū)嶋H上是一條一條指令,所以程序的運(yùn)行過(guò)程就是把每一條指令一步一步的執(zhí)行起來(lái),負(fù)責(zé)執(zhí)行指令的就是 CPU 了。

        「那 CPU 執(zhí)行程序的過(guò)程如下:」

        • 第一步,CPU 讀取程序計(jì)數(shù)器的值,這個(gè)值是指令的內(nèi)存地址,然后 CPU 的控制單元操作地址總線指定需要訪問(wèn)的內(nèi)存地址,接著通知內(nèi)存設(shè)備準(zhǔn)備數(shù)據(jù),數(shù)據(jù)準(zhǔn)備好后通過(guò)數(shù)據(jù)總線將指令數(shù)據(jù)傳給 CPU,CPU 收到內(nèi)存?zhèn)鱽?lái)的數(shù)據(jù)后,將這個(gè)指令數(shù)據(jù)存入到指令寄存器。
        • 第二步,CPU 分析指令寄存器中的指令,確定指令的類型和參數(shù),如果是計(jì)算類型的指令,就把指令交給邏輯運(yùn)算單元運(yùn)算;如果是存儲(chǔ)類型的指令,則交由控制單元執(zhí)行;
        • 第三步,CPU 執(zhí)行完指令后,程序計(jì)數(shù)器的值自增,表示指向下一條指令。這個(gè)自增的大小,由 CPU 的位寬決定,比如 32 位的 CPU,指令是 4 個(gè)字節(jié),需要 4 個(gè)內(nèi)存地址存放,因此程序計(jì)數(shù)器的值會(huì)自增 4;

        簡(jiǎn)單總結(jié)一下就是,一個(gè)程序執(zhí)行的時(shí)候,CPU 會(huì)根據(jù)程序計(jì)數(shù)器里的內(nèi)存地址,從內(nèi)存里面把需要執(zhí)行的指令讀取到指令寄存器里面執(zhí)行,然后根據(jù)指令長(zhǎng)度自增,開始順序讀取下一條指令。

        CPU 從程序計(jì)數(shù)器讀取指令、到執(zhí)行、再到下一條指令,這個(gè)過(guò)程會(huì)不斷循環(huán),直到程序執(zhí)行結(jié)束,這個(gè)不斷循環(huán)的過(guò)程被稱為 「CPU 的指令周期」。

        總線

        CPU 和內(nèi)存以及其他設(shè)備之間,也需要通信,因此我們用一種特殊的設(shè)備進(jìn)行控制,就是總線。

        • 地址總線,用于指定 CPU 將要操作的內(nèi)存地址;
        • 數(shù)據(jù)總線,用于讀寫內(nèi)存的數(shù)據(jù);
        • 控制總線,用于發(fā)送和接收信號(hào),比如中斷、設(shè)備復(fù)位等信號(hào),CPU 收到信號(hào)后自然進(jìn)行響應(yīng),這時(shí)也需要控制總線;

        當(dāng) CPU 要讀寫內(nèi)存數(shù)據(jù)的時(shí)候,一般需要通過(guò)兩個(gè)總線:

        • 首先要通過(guò)地址總線來(lái)指定內(nèi)存的地址;
        • 再通過(guò)數(shù)據(jù)總線來(lái)傳輸數(shù)據(jù);

        輸入、輸出設(shè)備

        輸入設(shè)備向計(jì)算機(jī)輸入數(shù)據(jù),計(jì)算機(jī)經(jīng)過(guò)計(jì)算,將結(jié)果通過(guò)輸出設(shè)備向外界傳達(dá)。

        如果輸入設(shè)備、輸出設(shè)備想要和 CPU 進(jìn)行交互,比如說(shuō)用戶按鍵需要 CPU 響應(yīng),這時(shí)候就需要用到控制總線。

        基礎(chǔ)知識(shí)

        中斷

        「中斷的類型」

        • 按照中斷的觸發(fā)方分成同步中斷和異步中斷;

        • 根據(jù)中斷是否強(qiáng)制觸發(fā)分成可屏蔽中斷和不可屏蔽中斷。

        中斷可以由 CPU 指令直接觸發(fā),這種主動(dòng)觸發(fā)的中斷,叫作同步中斷。

        ?

        同步中斷有幾種情況。

        ?
        • 比如系統(tǒng)調(diào)用,需要從用戶態(tài)切換內(nèi)核態(tài),這種情況需要程序觸發(fā)一個(gè)中斷,叫作陷阱(Trap),中斷觸發(fā)后需要繼續(xù)執(zhí)行系統(tǒng)調(diào)用。

        • 還有一種同步中斷情況是錯(cuò)誤(Fault),通常是因?yàn)闄z測(cè)到某種錯(cuò)誤,需要觸發(fā)一個(gè)中斷,中斷響應(yīng)結(jié)束后,會(huì)重新執(zhí)行觸發(fā)錯(cuò)誤的地方,比如后面我們要學(xué)習(xí)的缺頁(yè)中斷。

        • 最后還有一種情況是程序的異常,這種情況和 Trap 類似,用于實(shí)現(xiàn)程序拋出的異常。

        另一部分中斷不是由 CPU 直接觸發(fā),是因?yàn)樾枰憫?yīng)外部的通知,比如響應(yīng)鍵盤、鼠標(biāo)等設(shè)備而觸發(fā)的中斷,這種中斷我們稱為異步中斷。

        CPU 通常都支持設(shè)置一個(gè)中斷屏蔽位(一個(gè)寄存器),設(shè)置為 1 之后 CPU 暫時(shí)就不再響應(yīng)中斷。

        對(duì)于鍵盤鼠標(biāo)輸入,比如陷阱、錯(cuò)誤、異常等情況,會(huì)被臨時(shí)屏蔽。

        但是對(duì)于一些特別重要的中斷,比如 CPU 故障導(dǎo)致的掉電中斷,還是會(huì)正常觸發(fā)。

        「可以被屏蔽的中斷我們稱為可屏蔽中斷,多數(shù)中斷都是可屏蔽中斷?!?/strong>

        內(nèi)核態(tài)和用戶態(tài)

        「什么是用戶態(tài)和內(nèi)核態(tài)」

        Kernel 運(yùn)行在超級(jí)權(quán)限模式下,所以擁有很高的權(quán)限。

        按照權(quán)限管理的原則,多數(shù)應(yīng)用程序應(yīng)該運(yùn)行在最小權(quán)限下。

        因此,很多操作系統(tǒng),將內(nèi)存分成了兩個(gè)區(qū)域:

        • 內(nèi)核空間(Kernal Space),這個(gè)空間只有內(nèi)核程序可以訪問(wèn);

        • 用戶空間(User Space),這部分內(nèi)存專門給應(yīng)用程序使用。

        用戶空間中的代碼被限制了只能使用一個(gè)局部的內(nèi)存空間,我們說(shuō)這些程序在用戶態(tài) 執(zhí)行。

        內(nèi)核空間中的代碼可以訪問(wèn)所有內(nèi)存,我們稱這些程序在內(nèi)核態(tài) 執(zhí)行。

        ?

        按照級(jí)別分:

        ?

        當(dāng)程序運(yùn)行在0級(jí)特權(quán)級(jí)上時(shí),就可以稱之為運(yùn)行在內(nèi)核態(tài)

        當(dāng)程序運(yùn)行在3級(jí)特權(quán)級(jí)上時(shí),就可以稱之為運(yùn)行在用戶態(tài)

        運(yùn)行在用戶態(tài)下的程序不能直接訪問(wèn)操作系統(tǒng)內(nèi)核數(shù)據(jù)結(jié)構(gòu)和程序。

        當(dāng)我們?cè)谙到y(tǒng)中執(zhí)行一個(gè)程序時(shí),大部分時(shí)間是運(yùn)行在用戶態(tài)下的,在其需要操作系統(tǒng)幫助完成某些它沒(méi)有權(quán)力和能力完成的工作時(shí)就會(huì)切換到內(nèi)核態(tài)(比如操作硬件)

        「這兩種狀態(tài)的主要差別」

        處于用戶態(tài)執(zhí)行時(shí),進(jìn)程所能訪問(wèn)的內(nèi)存空間和對(duì)象受到限制,其所處于占有的處理器是可被搶占的

        處于內(nèi)核態(tài)執(zhí)行時(shí),則能訪問(wèn)所有的內(nèi)存空間和對(duì)象,且所占有的處理器是不允許被搶占的。

        「為什么要有用戶態(tài)和內(nèi)核態(tài)」

        由于需要限制不同的程序之間的訪問(wèn)能力,防止他們獲取別的程序的內(nèi)存數(shù)據(jù),或者獲取外圍設(shè)備的數(shù)據(jù),并發(fā)送到網(wǎng)絡(luò)

        「用戶態(tài)與內(nèi)核態(tài)的切換」

        所有用戶程序都是運(yùn)行在用戶態(tài)的,但是有時(shí)候程序確實(shí)需要做一些內(nèi)核態(tài)的事情, 例如從硬盤讀取數(shù)據(jù),或者從鍵盤獲取輸入等,而唯一可以做這些事情的就是操作系統(tǒng),所以此時(shí)程序就需要先操作系統(tǒng)請(qǐng)求以程序的名義來(lái)執(zhí)行這些操作

        「用戶態(tài)和內(nèi)核態(tài)的轉(zhuǎn)換」

        ?

        系統(tǒng)調(diào)用

        ?

        用戶態(tài)進(jìn)程通過(guò)系統(tǒng)調(diào)用申請(qǐng)使用操作系統(tǒng)提供的服務(wù)程序完成工作,比如fork()實(shí)際上就是執(zhí)行了一個(gè)創(chuàng)建新進(jìn)程的系統(tǒng)調(diào)用

        而系統(tǒng)調(diào)用的機(jī)制其核心還是使用了操作系統(tǒng)為用戶特別開放的一個(gè)中斷來(lái)實(shí)現(xiàn),例如Linux的int 80h中斷

        「舉例:」

        如上圖所示:內(nèi)核程序執(zhí)行在內(nèi)核態(tài)(Kernal Mode),用戶程序執(zhí)行在用戶態(tài)(User Mode)。

        當(dāng)發(fā)生系統(tǒng)調(diào)用時(shí),用戶態(tài)的程序發(fā)起系統(tǒng)調(diào)用,因?yàn)橄到y(tǒng)調(diào)用中牽扯特權(quán)指令,用戶態(tài)程序權(quán)限不足,因此會(huì)中斷執(zhí)行,也就是 Trap(Trap 是一種中斷)。

        發(fā)生中斷后,當(dāng)前 CPU 執(zhí)行的程序會(huì)中斷,跳轉(zhuǎn)到中斷處理程序,內(nèi)核程序開始執(zhí)行,也就是開始處理系統(tǒng)調(diào)用。

        內(nèi)核處理完成后,主動(dòng)觸發(fā) Trap,這樣會(huì)再次發(fā)生中斷,切換回用戶態(tài)工作。

        ?

        異常

        ?

        當(dāng)CPU在執(zhí)行運(yùn)行在用戶態(tài)下的程序時(shí),發(fā)生了某些事先不可知的異常,這時(shí)會(huì)觸發(fā)由當(dāng)前運(yùn)行進(jìn)程切換到處理此異常的內(nèi)核相關(guān)程序中,也就轉(zhuǎn)到了內(nèi)核態(tài),比如缺頁(yè)異常

        ?

        外圍設(shè)備的中斷

        ?

        當(dāng)外圍設(shè)備完成用戶請(qǐng)求的操作后,會(huì)向CPU發(fā)出相應(yīng)的中斷信號(hào),這時(shí)CPU會(huì)暫停執(zhí)行下一條即將要執(zhí)行的指令轉(zhuǎn)而去執(zhí)行與中斷信號(hào)對(duì)應(yīng)的處理程序,如果先前執(zhí)行的指令是用戶態(tài)下的程序,那么這個(gè)轉(zhuǎn)換的過(guò)程自然也就發(fā)生了由用戶態(tài)到內(nèi)核態(tài)的切換

        比如硬盤讀寫操作完成,系統(tǒng)會(huì)切換到硬盤讀寫的中斷處理程序中執(zhí)行后續(xù)操作等

        線程

        線程:系統(tǒng)分配處理器時(shí)間資源的基本單元,是程序執(zhí)行的最小單位

        線程可以看做輕量級(jí)的進(jìn)程,共享內(nèi)存空間,每個(gè)線程都有自己獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器,線程之間切換的開銷小。

        在同一個(gè)進(jìn)程(程序)中有多個(gè)線程同時(shí)執(zhí)行(通過(guò)CPU調(diào)度,在每個(gè)時(shí)間片中只有一個(gè)線程執(zhí)行)

        進(jìn)程可以通過(guò) API 創(chuàng)建用戶態(tài)的線程,也可以通過(guò)系統(tǒng)調(diào)用創(chuàng)建內(nèi)核態(tài)的線程。

        用戶態(tài)線程

        用戶態(tài)線程也稱作用戶級(jí)線程,操作系統(tǒng)內(nèi)核并不知道它的存在,它完全是在用戶空間中創(chuàng)建。

        用戶級(jí)線程有很多優(yōu)勢(shì),比如:

        • 管理開銷?。簞?chuàng)建、銷毀不需要系統(tǒng)調(diào)用。

        • 切換成本低:用戶空間程序可以自己維護(hù),不需要走操作系統(tǒng)調(diào)度。

        但是這種線程也有很多的缺點(diǎn):

        • 與內(nèi)核協(xié)作成本高:比如這種線程完全是用戶空間程序在管理,當(dāng)它進(jìn)行 I/O 的時(shí)候,無(wú)法利用到內(nèi)核的優(yōu)勢(shì),需要頻繁進(jìn)行用戶態(tài)到內(nèi)核態(tài)的切換。

        • 線程間協(xié)作成本高:設(shè)想兩個(gè)線程需要通信,通信需要 I/O,I/O 需要系統(tǒng)調(diào)用,因此用戶態(tài)線程需要額外的系統(tǒng)調(diào)用成本。

        • 無(wú)法利用多核優(yōu)勢(shì):比如操作系統(tǒng)調(diào)度的仍然是這個(gè)線程所屬的進(jìn)程,所以無(wú)論每次一個(gè)進(jìn)程有多少用戶態(tài)的線程,都只能并發(fā)執(zhí)行一個(gè)線程,因此一個(gè)進(jìn)程的多個(gè)線程無(wú)法利用多核的優(yōu)勢(shì)。

        操作系統(tǒng)無(wú)法針對(duì)線程調(diào)度進(jìn)行優(yōu)化:當(dāng)一個(gè)進(jìn)程的一個(gè)用戶態(tài)線程阻塞(Block)了,操作系統(tǒng)無(wú)法及時(shí)發(fā)現(xiàn)和處理阻塞問(wèn)題,它不會(huì)更換執(zhí)行其他線程,從而造成資源浪費(fèi)。

        內(nèi)核態(tài)線程

        內(nèi)核態(tài)線程也稱作內(nèi)核級(jí)線程(Kernel Level Thread),這種線程執(zhí)行在內(nèi)核態(tài),可以通過(guò)系統(tǒng)調(diào)用創(chuàng)造一個(gè)內(nèi)核級(jí)線程。

        內(nèi)核級(jí)線程有很多優(yōu)勢(shì):

        • 可以利用多核 CPU 優(yōu)勢(shì):內(nèi)核擁有較高權(quán)限,因此可以在多個(gè) CPU 核心上執(zhí)行內(nèi)核線程。

        • 操作系統(tǒng)級(jí)優(yōu)化:內(nèi)核中的線程操作 I/O 不需要進(jìn)行系統(tǒng)調(diào)用;一個(gè)內(nèi)核線程阻塞了,可以立即讓另一個(gè)執(zhí)行。

        當(dāng)然內(nèi)核線程也有一些缺點(diǎn):

        • 創(chuàng)建成本高:創(chuàng)建的時(shí)候需要系統(tǒng)調(diào)用,也就是切換到內(nèi)核態(tài)。

        • 擴(kuò)展性差:由一個(gè)內(nèi)核程序管理,不可能數(shù)量太多。

        • 切換成本較高:切換的時(shí)候,也同樣存在需要內(nèi)核操作,需要切換內(nèi)核態(tài)。

        「用戶態(tài)線程和內(nèi)核態(tài)線程之間的映射關(guān)系」

        如果有一個(gè)用戶態(tài)的進(jìn)程,它下面有多個(gè)線程,如果這個(gè)進(jìn)程想要執(zhí)行下面的某一個(gè)線程,應(yīng)該如何做呢?

        ?

        這時(shí),比較常見的一種方式,就是將需要執(zhí)行的程序,讓一個(gè)內(nèi)核線程去執(zhí)行。

        ?

        畢竟,內(nèi)核線程是真正的線程,因?yàn)樗鼤?huì)分配到 CPU 的執(zhí)行資源。

        如果一個(gè)進(jìn)程所有的線程都要自己調(diào)度,相當(dāng)于在進(jìn)程的主線程中實(shí)現(xiàn)分時(shí)算法調(diào)度每一個(gè)線程,也就是所有線程都用操作系統(tǒng)分配給主線程的時(shí)間片段執(zhí)行。

        ?

        這種做法,相當(dāng)于操作系統(tǒng)調(diào)度進(jìn)程的主線程;進(jìn)程的主線程進(jìn)行二級(jí)調(diào)度,調(diào)度自己內(nèi)部的線程。

        ?

        這樣操作劣勢(shì)非常明顯,比如無(wú)法利用多核優(yōu)勢(shì),每個(gè)線程調(diào)度分配到的時(shí)間較少,而且這種線程在阻塞場(chǎng)景下會(huì)直接交出整個(gè)進(jìn)程的執(zhí)行權(quán)限。

        由此可見,用戶態(tài)線程創(chuàng)建成本低,問(wèn)題明顯,不可以利用多核。

        內(nèi)核態(tài)線程,創(chuàng)建成本高,可以利用多核,切換速度慢。

        因此通常我們會(huì)在內(nèi)核中預(yù)先創(chuàng)建一些線程,并反復(fù)利用這些線程。

        協(xié)程

        協(xié)程,是一種比線程更加輕量級(jí)的存在,協(xié)程不是被操作系統(tǒng)內(nèi)核所管理,而完全是由程序所控制(也就是在用戶態(tài)執(zhí)行)。

        這樣帶來(lái)的好處就是性能得到了很大的提升,不會(huì)像線程切換那樣消耗資源。

        「子程序」

        或者稱為函數(shù),在所有語(yǔ)言中都是層級(jí)調(diào)用,比如A調(diào)用B,B在執(zhí)行過(guò)程中又調(diào)用了C,C執(zhí)行完畢返回,B執(zhí)行完畢返回,最后是A執(zhí)行完畢。

        所以子程序調(diào)用是通過(guò)棧實(shí)現(xiàn)的,一個(gè)線程就是執(zhí)行一個(gè)子程序。

        子程序調(diào)用總是一個(gè)入口,一次返回,調(diào)用順序是明確的。

        「協(xié)程的特點(diǎn)在于是一個(gè)線程執(zhí)行,那和多線程比,協(xié)程有何優(yōu)勢(shì)?」

        • 極高的執(zhí)行效率:因?yàn)樽映绦蚯袚Q不是線程切換,而是由程序自身控制,因此,沒(méi)有線程切換的開銷,和多線程比,線程數(shù)量越多,協(xié)程的性能優(yōu)勢(shì)就越明顯;
        • 不需要多線程的鎖機(jī)制:因?yàn)橹挥幸粋€(gè)線程,也不存在同時(shí)寫變量沖突,在協(xié)程中控制共享資源不加鎖,只需要判斷狀態(tài)就好了,所以執(zhí)行效率比多線程高很多。

        線程安全

        如果你的代碼所在的進(jìn)程中有多個(gè)線程在同時(shí)運(yùn)行,而這些線程可能會(huì)同時(shí)運(yùn)行這段代碼。

        如果每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線程安全的。

        進(jìn)程

        在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序;程序一旦運(yùn)行就是進(jìn)程;是資源分配的最小單位。

        在操作系統(tǒng)中能同時(shí)運(yùn)行多個(gè)進(jìn)程;

        開機(jī)的時(shí)候,磁盤的內(nèi)核鏡像被導(dǎo)入內(nèi)存作為一個(gè)執(zhí)行副本,成為內(nèi)核進(jìn)程。

        進(jìn)程可以分成「用戶態(tài)進(jìn)程和內(nèi)核態(tài)進(jìn)程」兩類,用戶態(tài)進(jìn)程通常是應(yīng)用程序的副本,內(nèi)核態(tài)進(jìn)程就是內(nèi)核本身的進(jìn)程。

        如果用戶態(tài)進(jìn)程需要申請(qǐng)資源,比如內(nèi)存,可以通過(guò)系統(tǒng)調(diào)用向內(nèi)核申請(qǐng)。

        每個(gè)進(jìn)程都有獨(dú)立的內(nèi)存空間,存放代碼和數(shù)據(jù)段等,程序之間的切換會(huì)有較大的開銷;

        「分時(shí)和調(diào)度」

        每個(gè)進(jìn)程在執(zhí)行時(shí)都會(huì)獲得操作系統(tǒng)分配的一個(gè)時(shí)間片段,如果超出這個(gè)時(shí)間,就會(huì)輪到下一個(gè)進(jìn)程(線程)執(zhí)行。

        ?

        注意,現(xiàn)代操作系統(tǒng)都是直接調(diào)度線程,不會(huì)調(diào)度進(jìn)程。

        ?

        「分配時(shí)間片段」

        如下圖所示,進(jìn)程 1 需要 2 個(gè)時(shí)間片段,進(jìn)程 2 只有 1 個(gè)時(shí)間片段,進(jìn)程 3 需要 3 個(gè)時(shí)間片段。

        因此當(dāng)進(jìn)程 1 執(zhí)行到一半時(shí),會(huì)先掛起,然后進(jìn)程 2 開始執(zhí)行;進(jìn)程 2 一次可以執(zhí)行完,然后進(jìn)程 3 開始執(zhí)行,不過(guò)進(jìn)程 3 一次執(zhí)行不完,在執(zhí)行了 1 個(gè)時(shí)間片段后,進(jìn)程 1 開始執(zhí)行;就這樣如此周而復(fù)始,這個(gè)就是分時(shí)技術(shù)。

        創(chuàng)建進(jìn)程

        用戶想要?jiǎng)?chuàng)建一個(gè)進(jìn)程,最直接的方法就是從命令行執(zhí)行一個(gè)程序,或者雙擊打開一個(gè)應(yīng)用,但對(duì)于程序員而言,顯然需要更好的設(shè)計(jì)。

        首先,應(yīng)該有 API 打開應(yīng)用,比如可以通過(guò)函數(shù)打開某個(gè)應(yīng)用;

        另一方面,如果程序員希望執(zhí)行完一段代價(jià)昂貴的初始化過(guò)程后,將當(dāng)前程序的狀態(tài)復(fù)制好幾份,變成一個(gè)個(gè)單獨(dú)執(zhí)行的進(jìn)程,那么操作系統(tǒng)提供了 fork 指令。

        也就是說(shuō),每次 fork 會(huì)多創(chuàng)造一個(gè)克隆的進(jìn)程,這個(gè)克隆的進(jìn)程,所有狀態(tài)都和原來(lái)的進(jìn)程一樣,但是會(huì)有自己的地址空間。

        如果要?jiǎng)?chuàng)造 2 個(gè)克隆進(jìn)程,就要 fork 兩次。

        ?

        那如果我就是想啟動(dòng)一個(gè)新的程序呢?

        ?

        操作系統(tǒng)提供了啟動(dòng)新程序的 API。

        如果我就是想用一個(gè)新進(jìn)程執(zhí)行一小段程序,比如說(shuō)每次服務(wù)端收到客戶端的請(qǐng)求時(shí),我都想用一個(gè)進(jìn)程去處理這個(gè)請(qǐng)求。

        如果是這種情況,建議你不要單獨(dú)啟動(dòng)進(jìn)程,而是使用線程。

        因?yàn)檫M(jìn)程的創(chuàng)建成本實(shí)在太高了,因此不建議用來(lái)做這樣的事情:要?jiǎng)?chuàng)建條目、要分配內(nèi)存,特別是還要在內(nèi)存中形成一個(gè)個(gè)段,分成不同的區(qū)域。所以通常,我們更傾向于多創(chuàng)建線程。

        不同程序語(yǔ)言會(huì)自己提供創(chuàng)建線程的 API,比如 Java 有 Thread 類;go 有 go-routine(注意不是協(xié)程,是線程)。

        進(jìn)程狀態(tài)

        「創(chuàng)建狀態(tài)」

        進(jìn)程由創(chuàng)建而產(chǎn)生,創(chuàng)建進(jìn)程是一個(gè)非常復(fù)雜的過(guò)程,一般需要通過(guò)多個(gè)步驟才能完成:如首先由進(jìn)程申請(qǐng)一個(gè)空白的進(jìn)程控制塊(PCB),并向PCB中填寫用于控制和管理進(jìn)程的信息;然后為該進(jìn)程分配運(yùn)行時(shí)所必須的資源;最后,把該進(jìn)程轉(zhuǎn)入就緒狀態(tài)并插入到就緒隊(duì)列中

        「就緒狀態(tài)」

        這是指進(jìn)程已經(jīng)準(zhǔn)備好運(yùn)行的狀態(tài),即進(jìn)程已分配到除CPU以外所有的必要資源后,只要再獲得CPU,便可立即執(zhí)行,如果系統(tǒng)中有許多處于就緒狀態(tài)的進(jìn)程,通常將它們按照一定的策略排成一個(gè)隊(duì)列,該隊(duì)列稱為就緒隊(duì)列,有執(zhí)行資格,沒(méi)有執(zhí)行權(quán)的進(jìn)程

        「運(yùn)行狀態(tài)」

        這里指進(jìn)程已經(jīng)獲取CPU,其進(jìn)程處于正在執(zhí)行的狀態(tài)。對(duì)任何一個(gè)時(shí)刻而言,在單處理機(jī)的系統(tǒng)中,只有一個(gè)進(jìn)程處于執(zhí)行狀態(tài)而在多處理機(jī)系統(tǒng)中,有多個(gè)進(jìn)程處于執(zhí)行狀態(tài),既有執(zhí)行資格,又有執(zhí)行權(quán)的進(jìn)程

        「阻塞狀態(tài)」

        這里是指正在執(zhí)行的進(jìn)程由于發(fā)生某事件(如I/O請(qǐng)求、申請(qǐng)緩沖區(qū)失敗等)暫時(shí)無(wú)法繼續(xù)執(zhí)行的狀態(tài),即進(jìn)程執(zhí)行受到阻塞,此時(shí)引起進(jìn)程調(diào)度,操作系統(tǒng)把處理機(jī)分配給另外一個(gè)就緒的進(jìn)程,而讓受阻的進(jìn)程處于暫停的狀態(tài),一般將這個(gè)暫停狀態(tài)稱為阻塞狀態(tài)

        「終止?fàn)顟B(tài)」

        進(jìn)程間通信IPC

        每個(gè)進(jìn)程各自有不同的用戶地址空間,任何一個(gè)進(jìn)程的全局變量在另一個(gè)進(jìn)程中都看不到,所以進(jìn)程之間要交換數(shù)據(jù)必須通過(guò)內(nèi)核,在內(nèi)核中開辟一塊緩沖區(qū),進(jìn)程1把數(shù)據(jù)從用戶空間拷到內(nèi)核緩沖區(qū),進(jìn)程2再?gòu)膬?nèi)核緩沖區(qū)把數(shù)據(jù)讀走,內(nèi)核提供的這種機(jī)制稱為進(jìn)程間通信

        「管道/匿名管道」

        管道是半雙工的,數(shù)據(jù)只能向一個(gè)方向流動(dòng);需要雙方通信時(shí),需要建立起兩個(gè)管道。

        • 只能用于父子進(jìn)程或者兄弟進(jìn)程之間(具有親緣關(guān)系的進(jìn)程);

        • 單獨(dú)構(gòu)成一種獨(dú)立的文件系統(tǒng):管道對(duì)于管道兩端的進(jìn)程而言,就是一個(gè)文件,但它不是普通的文件,它不屬于某種文件系統(tǒng),而是自立門戶,單獨(dú)構(gòu)成一種文件系統(tǒng),并且只存在與內(nèi)存中。

        • 數(shù)據(jù)的讀出和寫入:一個(gè)進(jìn)程向管道中寫的內(nèi)容被管道另一端的進(jìn)程讀出,寫入的內(nèi)容每次都添加在管道緩沖區(qū)的末尾,并且每次都是從緩沖區(qū)的頭部讀出數(shù)據(jù)。

        「有名管道(FIFO)」

        匿名管道,由于沒(méi)有名字,只能用于親緣關(guān)系的進(jìn)程間通信。

        為了克服這個(gè)缺點(diǎn),提出了有名管道(FIFO)。

        有名管道不同于匿名管道之處在于它提供了一個(gè)路徑名與之關(guān)聯(lián),以有名管道的文件形式存在于文件系統(tǒng)中,這樣,即使與有名管道的創(chuàng)建進(jìn)程不存在親緣關(guān)系的進(jìn)程,只要可以訪問(wèn)該路徑,就能夠彼此通過(guò)有名管道相互通信,因此,通過(guò)有名管道不相關(guān)的進(jìn)程也能交換數(shù)據(jù)。

        「信號(hào)」

        信號(hào)是Linux系統(tǒng)中用于進(jìn)程間互相通信或者操作的一種機(jī)制,信號(hào)可以在任何時(shí)候發(fā)給某一進(jìn)程,而無(wú)需知道該進(jìn)程的狀態(tài)。

        如果該進(jìn)程當(dāng)前并未處于執(zhí)行狀態(tài),則該信號(hào)就有內(nèi)核保存起來(lái),知道該進(jìn)程回復(fù)執(zhí)行并傳遞給它為止。

        如果一個(gè)信號(hào)被進(jìn)程設(shè)置為阻塞,則該信號(hào)的傳遞被延遲,直到其阻塞被取消是才被傳遞給進(jìn)程。

        「消息隊(duì)列」

        消息隊(duì)列是存放在內(nèi)核中的消息鏈表,每個(gè)消息隊(duì)列由消息隊(duì)列標(biāo)識(shí)符表示。

        與管道(無(wú)名管道:只存在于內(nèi)存中的文件;命名管道:存在于實(shí)際的磁盤介質(zhì)或者文件系統(tǒng))不同的是消息隊(duì)列存放在內(nèi)核中,只有在內(nèi)核重啟(即操作系統(tǒng)重啟)或者顯示地刪除一個(gè)消息隊(duì)列時(shí),該消息隊(duì)列才會(huì)被真正的刪除。

        另外與管道不同的是,消息隊(duì)列在某個(gè)進(jìn)程往一個(gè)隊(duì)列寫入消息之前,并不需要另外某個(gè)進(jìn)程在該隊(duì)列上等待消息的到達(dá)

        「共享內(nèi)存」

        使得多個(gè)進(jìn)程可以直接讀寫同一塊內(nèi)存空間,是最快的可用IPC形式,是針對(duì)其他通信機(jī)制運(yùn)行效率較低而設(shè)計(jì)的。

        為了在多個(gè)進(jìn)程間交換信息,內(nèi)核專門留出了一塊內(nèi)存區(qū),可以由需要訪問(wèn)的進(jìn)程將其映射到自己的私有地址空間,進(jìn)程就可以直接讀寫這一塊內(nèi)存而不需要進(jìn)行數(shù)據(jù)的拷貝,從而大大提高效率。

        由于多個(gè)進(jìn)程共享一段內(nèi)存,因此需要依靠某種同步機(jī)制(如信號(hào)量)來(lái)達(dá)到進(jìn)程間的同步及互斥。

        共享內(nèi)存示意圖:

        一旦這樣的內(nèi)存映射到共享它的進(jìn)程的地址空間,這些進(jìn)程間數(shù)據(jù)傳遞不再涉及到內(nèi)核,換句話說(shuō)是進(jìn)程不再通過(guò)執(zhí)行進(jìn)入內(nèi)核的系統(tǒng)調(diào)用來(lái)傳遞彼此的數(shù)據(jù)。

        「信號(hào)量」

        信號(hào)量是一個(gè)計(jì)數(shù)器,用于多進(jìn)程對(duì)共享數(shù)據(jù)的訪問(wèn),信號(hào)量的意圖在于進(jìn)程間同步。

        為了獲得共享資源,進(jìn)程需要執(zhí)行下列操作:

        1. 創(chuàng)建一個(gè)信號(hào)量:這要求調(diào)用者指定初始值,對(duì)于二值信號(hào)量來(lái)說(shuō),它通常是1,也可是0。

        2. 等待一個(gè)信號(hào)量:該操作會(huì)測(cè)試這個(gè)信號(hào)量的值,如果小于0,就阻塞,也稱為P操作。

        3. 掛出一個(gè)信號(hào)量:該操作將信號(hào)量的值加1,也稱為V操作。

        「套接字(Socket)」

        套接字是一種通信機(jī)制,憑借這種機(jī)制,客戶/服務(wù)器(即要進(jìn)行通信的進(jìn)程)系統(tǒng)的開發(fā)工作既可以在本地單機(jī)上進(jìn)行,也可以跨網(wǎng)絡(luò)進(jìn)行。也就是說(shuō)它可以讓不在同一臺(tái)計(jì)算機(jī)但通過(guò)網(wǎng)絡(luò)連接計(jì)算機(jī)上的進(jìn)程進(jìn)行通信。

        信號(hào)

        信號(hào)是進(jìn)程間通信機(jī)制中唯一的異步通信機(jī)制,可以看作是異步通知,通知接收信號(hào)的進(jìn)程有哪些事情發(fā)生了。

        也可以簡(jiǎn)單理解為信號(hào)是某種形式上的軟中斷

        可運(yùn)行kill -l查看Linux支持的信號(hào)列表:

        kill -l
         1) SIGHUP  2) SIGINT  3) SIGQUIT  4) SIGILL  5) SIGTRAP
         6) SIGABRT  7) SIGBUS  8) SIGFPE  9) SIGKILL 10) SIGUSR1
        11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
        16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
        21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
        26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
        31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
        38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
        43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
        48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
        53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
        58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
        63) SIGRTMAX-1 64) SIGRTMAX

        「幾個(gè)常用的信號(hào):」

        信號(hào)描述
        SIGHUP當(dāng)用戶退出終端時(shí),由該終端開啟的所有進(jìn)程都會(huì)接收到這個(gè)信號(hào),默認(rèn)動(dòng)作為終止進(jìn)程。
        SIGINT程序終止(interrupt)信號(hào), 在用戶鍵入INTR字符(通常是Ctrl+C)時(shí)發(fā)出,用于通知前臺(tái)進(jìn)程組終止進(jìn)程。
        SIGQUITSIGINT類似, 但由QUIT字符(通常是Ctrl+\)來(lái)控制,進(jìn)程在因收到SIGQUIT退出時(shí)會(huì)產(chǎn)生core文件, 在這個(gè)意義上類似于一個(gè)程序錯(cuò)誤信號(hào)。
        SIGKILL用來(lái)立即結(jié)束程序的運(yùn)行,本信號(hào)不能被阻塞、處理和忽略。
        SIGTERM程序結(jié)束(terminate)信號(hào), 與SIGKILL不同的是該信號(hào)可以被阻塞和處理。通常用來(lái)要求程序自己正常退出。
        SIGSTOP停止(stopped)進(jìn)程的執(zhí)行. 注意它和terminate以及interrupt的區(qū)別:該進(jìn)程還未結(jié)束, 只是暫停執(zhí)行,本信號(hào)不能被阻塞, 處理或忽略

        進(jìn)程同步

        「臨界區(qū)」

        通過(guò)對(duì)多線程的串行化來(lái)訪問(wèn)公共資源或一段代碼,速度快,適合控制數(shù)據(jù)訪問(wèn)

        優(yōu)點(diǎn):保證在某一時(shí)刻只有一個(gè)線程能訪問(wèn)數(shù)據(jù)的簡(jiǎn)便辦法

        缺點(diǎn):雖然臨界區(qū)同步速度很快,但卻只能用來(lái)同步本進(jìn)程內(nèi)的線程,而不可用來(lái)同步多個(gè)進(jìn)程中的線程

        「互斥量」

        為協(xié)調(diào)共同對(duì)一個(gè)共享資源的單獨(dú)訪問(wèn)而設(shè)計(jì)的

        互斥量跟臨界區(qū)很相似,比臨界區(qū)復(fù)雜,互斥對(duì)象只有一個(gè),只有擁有互斥對(duì)象的線程才具有訪問(wèn)資源的權(quán)限

        優(yōu)點(diǎn):使用互斥不僅僅能夠在同一應(yīng)用程序不同線程中實(shí)現(xiàn)資源的安全共享,而且可以在不同應(yīng)用程序的線程之間實(shí)現(xiàn)對(duì)資源的安全共享

        「信號(hào)量」

        為控制一個(gè)具有有限數(shù)量用戶資源而設(shè)計(jì),它允許多個(gè)線程在同一時(shí)刻訪問(wèn)同一資源,但是需要限制在同一時(shí)刻訪問(wèn)此資源的最大線程數(shù)目,互斥量是信號(hào)量的一種特殊情況,當(dāng)信號(hào)量的最大資源數(shù)=1就是互斥量了

        信號(hào)量(Semaphore)是一個(gè)整型變量,可以對(duì)其執(zhí)行 down 和 up 操作,也就是常見的 P 和 V 操作

        • 「down」 : 如果信號(hào)量大于 0 ,執(zhí)行 -1 操作;如果信號(hào)量等于 0,進(jìn)程睡眠,等待信號(hào)量大于 0;
        • 「up」 :對(duì)信號(hào)量執(zhí)行 +1 操作,喚醒睡眠的進(jìn)程讓其完成 down 操作。

        down 和 up 操作需要被設(shè)計(jì)成原語(yǔ),不可分割,通常的做法是在執(zhí)行這些操作的時(shí)候屏蔽中斷。

        如果信號(hào)量的取值只能為 0 或者 1,那么就成為了 「互斥量(Mutex)」 ,0 表示臨界區(qū)已經(jīng)加鎖,1 表示臨界區(qū)解鎖。

        「事件」

        用來(lái)通知線程有一些事件已發(fā)生,從而啟動(dòng)后繼任務(wù)的開始

        優(yōu)點(diǎn):事件對(duì)象通過(guò)通知操作的方式來(lái)保持線程的同步,并且可以實(shí)現(xiàn)不同進(jìn)程中的線程同步操作

        「管程」

        管程有一個(gè)重要特性:在一個(gè)時(shí)刻只能有一個(gè)進(jìn)程使用管程。

        進(jìn)程在無(wú)法繼續(xù)執(zhí)行的時(shí)候不能一直占用管程,否則其它進(jìn)程永遠(yuǎn)不能使用管程。

        管程引入了 「條件變量」 以及相關(guān)的操作:「wait()」「signal()」 來(lái)實(shí)現(xiàn)同步操作。

        對(duì)條件變量執(zhí)行 wait() 操作會(huì)導(dǎo)致調(diào)用進(jìn)程阻塞,把管程讓出來(lái)給另一個(gè)進(jìn)程持有。

        signal() 操作用于喚醒被阻塞的進(jìn)程。

        使用信號(hào)量機(jī)制實(shí)現(xiàn)的生產(chǎn)者消費(fèi)者問(wèn)題需要客戶端代碼做很多控制,而管程把控制的代碼獨(dú)立出來(lái),不僅不容易出錯(cuò),也使得客戶端代碼調(diào)用更容易。

        上下文切換

        對(duì)于單核單線程CPU而言,在某一時(shí)刻只能執(zhí)行一條CPU指令。

        上下文切換(Context Switch)是一種將CPU資源從一個(gè)進(jìn)程分配給另一個(gè)進(jìn)程的機(jī)制。

        從用戶角度看,計(jì)算機(jī)能夠并行運(yùn)行多個(gè)進(jìn)程,這恰恰是操作系統(tǒng)通過(guò)快速上下文切換造成的結(jié)果。

        「在切換的過(guò)程中,操作系統(tǒng)需要先存儲(chǔ)當(dāng)前進(jìn)程的狀態(tài)(包括內(nèi)存空間的指針,當(dāng)前執(zhí)行完的指令等等),再讀入下一個(gè)進(jìn)程的狀態(tài),然后執(zhí)行此進(jìn)程。」

        進(jìn)程調(diào)度算法

        「先來(lái)先服務(wù)調(diào)度算法」

        該算法既可用于作業(yè)調(diào)度,也可用于進(jìn)程調(diào)度,當(dāng)在作業(yè)調(diào)度中采用該算法時(shí),每次調(diào)度都是從后備作業(yè)隊(duì)列中選擇一個(gè)或多個(gè)最先進(jìn)入該隊(duì)列的作業(yè),將它們調(diào)入內(nèi)存,為它們分配資源、創(chuàng)建進(jìn)程,然后放入就緒隊(duì)列

        「短作業(yè)優(yōu)先調(diào)度算法」

        從后備隊(duì)列中選擇一個(gè)或若干個(gè)估計(jì)運(yùn)行時(shí)間最短的作業(yè),將它們調(diào)入內(nèi)存運(yùn)行

        「時(shí)間片輪轉(zhuǎn)法」

        每次調(diào)度時(shí),把CPU分配給隊(duì)首進(jìn)程,并令其執(zhí)行一個(gè)時(shí)間片,時(shí)間片的大小從幾ms到幾百ms,當(dāng)執(zhí)行的時(shí)間片用完時(shí),由一個(gè)計(jì)時(shí)器發(fā)出時(shí)鐘中斷請(qǐng)求,調(diào)度程序便據(jù)此信號(hào)來(lái)停止該進(jìn)程的執(zhí)行,并將它送往就緒隊(duì)列的末尾

        然后,再把處理機(jī)分配給就緒隊(duì)列中新的隊(duì)首進(jìn)程,同時(shí)也讓它執(zhí)行一個(gè)時(shí)間片,這樣就可以保證就緒隊(duì)列中的所有進(jìn)程在一給定的時(shí)間內(nèi)均能獲得一時(shí)間片的處理機(jī)執(zhí)行時(shí)間

        「最短剩余時(shí)間優(yōu)先」

        最短作業(yè)優(yōu)先的搶占式版本,按剩余運(yùn)行時(shí)間的順序進(jìn)行調(diào)度,當(dāng)一個(gè)新的作業(yè)到達(dá)時(shí),其整個(gè)運(yùn)行時(shí)間與當(dāng)前進(jìn)程的剩余時(shí)間作比較。

        如果新的進(jìn)程需要的時(shí)間更少,則掛起當(dāng)前進(jìn)程,運(yùn)行新的進(jìn)程。否則新的進(jìn)程等待。

        「多級(jí)反饋隊(duì)列調(diào)度算法」

        前面介紹的幾種進(jìn)程調(diào)度的算法都有一定的局限性,如「短進(jìn)程優(yōu)先的調(diào)度算法,僅照顧了短進(jìn)程而忽略了長(zhǎng)進(jìn)程」,多級(jí)反饋隊(duì)列調(diào)度算法既能使高優(yōu)先級(jí)的作業(yè)得到響應(yīng)又能使短作業(yè)迅速完成,因而它是目前「被公認(rèn)的一種較好的進(jìn)程調(diào)度算法」,UNIX 操作系統(tǒng)采取的便是這種調(diào)度算法。

        ?

        舉例:

        ?

        多級(jí)隊(duì)列,就是多個(gè)隊(duì)列執(zhí)行調(diào)度,先考慮最簡(jiǎn)單的兩級(jí)模型

        上圖中設(shè)計(jì)了兩個(gè)優(yōu)先級(jí)不同的隊(duì)列,從下到上優(yōu)先級(jí)上升,上層隊(duì)列調(diào)度緊急任務(wù),下層隊(duì)列調(diào)度普通任務(wù)。

        只要上層隊(duì)列有任務(wù),下層隊(duì)列就會(huì)讓出執(zhí)行權(quán)限。

        低優(yōu)先級(jí)隊(duì)列可以考慮搶占 + 優(yōu)先級(jí)隊(duì)列的方式實(shí)現(xiàn),這樣每次執(zhí)行一個(gè)時(shí)間片段就可以判斷一下高優(yōu)先級(jí)的隊(duì)列中是否有任務(wù)。

        高優(yōu)先級(jí)隊(duì)列可以考慮用非搶占(每個(gè)任務(wù)執(zhí)行完才執(zhí)行下一個(gè))+ 優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn),這樣緊急任務(wù)優(yōu)先級(jí)有個(gè)區(qū)分,如果遇到十萬(wàn)火急的情況,就可以優(yōu)先處理這個(gè)任務(wù)。

        上面這個(gè)模型雖然解決了任務(wù)間的優(yōu)先級(jí)問(wèn)題,但是還是沒(méi)有解決短任務(wù)先行的問(wèn)題,可以考慮再增加一些隊(duì)列,讓級(jí)別更多。

        ?

        比如下圖這個(gè)模型:

        ?

        緊急任務(wù)仍然走高優(yōu)隊(duì)列,非搶占執(zhí)行。

        普通任務(wù)先放到優(yōu)先級(jí)僅次于高優(yōu)任務(wù)的隊(duì)列中,并且只分配很小的時(shí)間片;如果沒(méi)有執(zhí)行完成,說(shuō)明任務(wù)不是很短,就將任務(wù)下調(diào)一層。

        下面一層,最低優(yōu)先級(jí)的隊(duì)列中時(shí)間片很大,長(zhǎng)任務(wù)就有更大的時(shí)間片可以用。

        通過(guò)這種方式,短任務(wù)會(huì)在更高優(yōu)先級(jí)的隊(duì)列中執(zhí)行完成,長(zhǎng)任務(wù)優(yōu)先級(jí)會(huì)下調(diào),也就類似實(shí)現(xiàn)了最短作業(yè)優(yōu)先的問(wèn)題。

        實(shí)際操作中,可以有 n 層,一層層把大任務(wù)篩選出來(lái),最長(zhǎng)的任務(wù),放到最閑的時(shí)間去執(zhí)行,要知道,大部分時(shí)間 CPU 不是滿負(fù)荷的。

        「優(yōu)先級(jí)調(diào)度」

        為每個(gè)流程分配優(yōu)先級(jí),首先執(zhí)行具有最高優(yōu)先級(jí)的進(jìn)程,依此類推,具有相同優(yōu)先級(jí)的進(jìn)程以 FCFS 方式執(zhí)行,可以根據(jù)內(nèi)存要求,時(shí)間要求或任何其他資源要求來(lái)確定優(yōu)先級(jí)。

        守護(hù)進(jìn)程

        守護(hù)進(jìn)程是脫離于終端并且在后臺(tái)運(yùn)行的進(jìn)程,脫離終端是為了避免在執(zhí)行的過(guò)程中的信息在終端上顯示,并且進(jìn)程也不會(huì)被任何終端所產(chǎn)生的終端信息所打斷。

        守護(hù)進(jìn)程一般的生命周期是系統(tǒng)啟動(dòng)到系統(tǒng)停止運(yùn)行。

        Linux系統(tǒng)中有很多的守護(hù)進(jìn)程,最典型的就是我們經(jīng)??吹降姆?wù)進(jìn)程。

        當(dāng)然,我們也經(jīng)常會(huì)利用守護(hù)進(jìn)程來(lái)完成很多的系統(tǒng)或者自動(dòng)化任務(wù)。

        孤兒進(jìn)程

        父進(jìn)程早于子進(jìn)程退出時(shí)候子進(jìn)程還在運(yùn)行,子進(jìn)程會(huì)成為孤兒進(jìn)程,Linux會(huì)對(duì)孤兒進(jìn)程的處理,把孤兒進(jìn)程的父進(jìn)程設(shè)為進(jìn)程號(hào)為1的進(jìn)程,也就是由init進(jìn)程來(lái)托管,init進(jìn)程負(fù)責(zé)子進(jìn)程退出后的善后清理工作

        僵尸進(jìn)程

        子進(jìn)程執(zhí)行完畢時(shí)發(fā)現(xiàn)父進(jìn)程未退出,會(huì)向父進(jìn)程發(fā)送 SIGCHLD 信號(hào),但父進(jìn)程沒(méi)有使用 wait/waitpid 或其他方式處理 SIGCHLD 信號(hào)來(lái)回收子進(jìn)程,子進(jìn)程變成為了對(duì)系統(tǒng)有害的僵尸進(jìn)程

        子進(jìn)程退出后留下的進(jìn)程信息沒(méi)有被收集,會(huì)導(dǎo)致占用的進(jìn)程控制塊PCB不被釋放,形成僵尸進(jìn)程,進(jìn)程已經(jīng)死去,但是進(jìn)程資源沒(méi)有被釋放掉

        「問(wèn)題及危害」

        如果系統(tǒng)中存在大量的僵尸進(jìn)程,他們的進(jìn)程號(hào)就會(huì)一直被占用,但是系統(tǒng)所能使用的進(jìn)程號(hào)是有限的,系統(tǒng)將因?yàn)闆](méi)有可用的進(jìn)程號(hào)而導(dǎo)致系統(tǒng)不能產(chǎn)生新的進(jìn)程

        任何一個(gè)子進(jìn)程(init除外)在exit()之后,并非馬上就消失掉,而是留下一個(gè)稱為僵尸進(jìn)程(Zombie)的數(shù)據(jù)結(jié)構(gòu),等待父進(jìn)程處理,這是每個(gè)子進(jìn)程在結(jié)束時(shí)都要經(jīng)過(guò)的階段,如果子進(jìn)程在exit()之后,父進(jìn)程沒(méi)有來(lái)得及處理,這時(shí)用ps命令就能看到子進(jìn)程的狀態(tài)是Z。

        如果父進(jìn)程能及時(shí)處理,可能用ps命令就來(lái)不及看到子進(jìn)程的僵尸狀態(tài),但這并不等于子進(jìn)程不經(jīng)過(guò)僵尸狀態(tài)

        產(chǎn)生僵尸進(jìn)程的元兇其實(shí)是他們的父進(jìn)程,殺掉父進(jìn)程,僵尸進(jìn)程就變?yōu)榱斯聝哼M(jìn)程,便可以轉(zhuǎn)交給 init 進(jìn)程回收處理

        死鎖

        「產(chǎn)生原因」

        系統(tǒng)資源的競(jìng)爭(zhēng):系統(tǒng)資源的競(jìng)爭(zhēng)導(dǎo)致系統(tǒng)資源不足,以及資源分配不當(dāng),導(dǎo)致死鎖。

        進(jìn)程運(yùn)行推進(jìn)順序不合適:進(jìn)程在運(yùn)行過(guò)程中,請(qǐng)求和釋放資源的順序不當(dāng),會(huì)導(dǎo)致死鎖。

        「發(fā)生死鎖的四個(gè)必要條件」

        互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用,即在一段時(shí)間內(nèi)某資源僅為一個(gè)進(jìn)程所占有,此時(shí)若有其他進(jìn)程請(qǐng)求該資源,則請(qǐng)求進(jìn)程只能等待

        請(qǐng)求與保持條件:進(jìn)程已經(jīng)保持了至少一個(gè)資源,但又提出了新的資源請(qǐng)求時(shí),該資源已被其他進(jìn)程占有,此時(shí)請(qǐng)求進(jìn)程被阻塞,但對(duì)自己已獲得的資源保持不放

        不可剝奪條件:進(jìn)程所獲得的資源在未使用完畢之前,不能被其他進(jìn)程強(qiáng)行奪走,即只能由獲得該資源的進(jìn)程自己來(lái)釋放(只能是主動(dòng)釋放)

        循環(huán)等待條件: 若干進(jìn)程間形成首尾相接循環(huán)等待資源的關(guān)系

        這四個(gè)條件是死鎖的必要條件,只要系統(tǒng)發(fā)生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會(huì)發(fā)生死鎖

        「只要我們破壞其中一個(gè),就可以成功避免死鎖的發(fā)生」

        其中,互斥這個(gè)條件我們沒(méi)有辦法破壞,因?yàn)槲覀冇面i為的就是互斥

        1. 對(duì)于占用且等待這個(gè)條件,我們可以一次性申請(qǐng)所有的資源,這樣就不存在等待了。
        2. 對(duì)于不可搶占這個(gè)條件,占用部分資源的線程進(jìn)一步申請(qǐng)其他資源時(shí),如果申請(qǐng)不到,可以主動(dòng)釋放它占有的資源,這樣不可搶占這個(gè)條件就破壞掉了。
        3. 對(duì)于循環(huán)等待這個(gè)條件,可以靠按序申請(qǐng)資源來(lái)預(yù)防,所謂按序申請(qǐng),是指資源是有線性順序的,申請(qǐng)的時(shí)候可以先申請(qǐng)資源序號(hào)小的,再申請(qǐng)資源序號(hào)大的,這樣線性化后自然就不存在循環(huán)了。

        「處理方法」

        主要有以下四種方法:

        • 鴕鳥策略
        • 死鎖檢測(cè)與死鎖恢復(fù)
        • 死鎖預(yù)防,破壞4個(gè)必要條件
        • 死鎖避免,銀行家算法

        「鴕鳥策略」

        把頭埋在沙子里,假裝根本沒(méi)發(fā)生問(wèn)題。

        因?yàn)榻鉀Q死鎖問(wèn)題的代價(jià)很高,因此鴕鳥策略這種不采取任務(wù)措施的方案會(huì)獲得更高的性能。

        當(dāng)發(fā)生死鎖時(shí)不會(huì)對(duì)用戶造成多大影響,或發(fā)生死鎖的概率很低,可以采用鴕鳥策略。

        「死鎖檢測(cè)」

        不試圖阻止死鎖,而是當(dāng)檢測(cè)到死鎖發(fā)生時(shí),采取措施進(jìn)行恢復(fù)。

        1. 每種類型一個(gè)資源的死鎖檢測(cè)

        2. 每種類型多個(gè)資源的死鎖檢測(cè)

        「死鎖恢復(fù)」

        • 利用搶占恢復(fù)
        • 利用回滾恢復(fù)
        • 通過(guò)殺死進(jìn)程恢復(fù)

        哲學(xué)家進(jìn)餐問(wèn)題

        五個(gè)哲學(xué)家圍著一張圓桌,每個(gè)哲學(xué)家面前放著食物。

        哲學(xué)家的生活有兩種交替活動(dòng):吃飯以及思考。

        當(dāng)一個(gè)哲學(xué)家吃飯時(shí),需要先拿起自己左右兩邊的兩根筷子,并且一次只能拿起一根筷子。

        如果所有哲學(xué)家同時(shí)拿起左手邊的筷子,那么所有哲學(xué)家都在等待其它哲學(xué)家吃完并釋放自己手中的筷子,導(dǎo)致死鎖。

        哲學(xué)家進(jìn)餐問(wèn)題可看作是并發(fā)進(jìn)程并發(fā)執(zhí)行時(shí)處理共享資源的一個(gè)有代表性的問(wèn)題。

        「為了防止死鎖的發(fā)生,可以設(shè)置兩個(gè)條件:」

        • 必須同時(shí)拿起左右兩根筷子;
        • 只有在兩個(gè)鄰居都沒(méi)有進(jìn)餐的情況下才允許進(jìn)餐。

        銀行家算法

        銀行家算法的命名是它可以用了銀行系統(tǒng),當(dāng)不能滿足所有客戶的需求時(shí),銀行絕不會(huì)分配其資金。

        當(dāng)新進(jìn)程進(jìn)入系統(tǒng)時(shí),它必須說(shuō)明其可能需要的每種類型資源實(shí)例的最大數(shù)量這一數(shù)量不可以超過(guò)系統(tǒng)資源的總和。

        當(dāng)用戶申請(qǐng)一組資源時(shí),系統(tǒng)必須確定這些資源的分配是否處于安全狀態(tài),如何安全,則分配,如果不安全,那么進(jìn)程必須等待指導(dǎo)某個(gè)其他進(jìn)程釋放足夠資源為止。

        「安全狀態(tài)」

        在避免死鎖的方法中,允許進(jìn)程動(dòng)態(tài)地申請(qǐng)資源,但系統(tǒng)在進(jìn)行資源分配之前,應(yīng)先計(jì)算此次資源分配的安全性,若此次分配不會(huì)導(dǎo)致系統(tǒng)進(jìn)入不安全狀態(tài),則將資源分配給進(jìn)程;否則,令進(jìn)程等待

        因此,避免死鎖的實(shí)質(zhì)在于:系統(tǒng)在進(jìn)行資源分配時(shí),如何使系統(tǒng)不進(jìn)入不安全狀態(tài)

        Fork函數(shù)

        fork函數(shù)用于創(chuàng)建一個(gè)與當(dāng)前進(jìn)程一樣的子進(jìn)程,所創(chuàng)建的子進(jìn)程將復(fù)制父進(jìn)程的代碼段、數(shù)據(jù)段、BSS段、堆、棧等所有用戶空間信息,在內(nèi)核中操作系統(tǒng)會(huì)重新為其申請(qǐng)一個(gè)子進(jìn)程執(zhí)行的位置。

        fork系統(tǒng)調(diào)用會(huì)通過(guò)復(fù)制一個(gè)現(xiàn)有進(jìn)程來(lái)創(chuàng)建一個(gè)全新的進(jìn)程,新進(jìn)程被存放在一個(gè)叫做任務(wù)隊(duì)列的雙向循環(huán)鏈表中,鏈表中的每一項(xiàng)都是類型為task_struct的進(jìn)程控制塊PCB的結(jié)構(gòu)。

        每個(gè)進(jìn)程都由獨(dú)特?fù)Q不相同的進(jìn)程標(biāo)識(shí)符(PID),通過(guò)getpid()函數(shù)可獲取當(dāng)前進(jìn)程的進(jìn)程標(biāo)識(shí)符,通過(guò)getppid()函數(shù)可獲得父進(jìn)程的進(jìn)程標(biāo)識(shí)符。

        一個(gè)現(xiàn)有的進(jìn)程可通過(guò)調(diào)用fork函數(shù)創(chuàng)建一個(gè)新進(jìn)程,由fork創(chuàng)建的新進(jìn)程稱為子進(jìn)程child process,fork函數(shù)被調(diào)用一次但返回兩次,兩次返回的唯一區(qū)別是子進(jìn)程中返回0而父進(jìn)程中返回子進(jìn)程ID。

        「為什么fork會(huì)返回兩次呢?」

        因?yàn)閺?fù)制時(shí)會(huì)復(fù)制父進(jìn)程的堆棧段,所以兩個(gè)進(jìn)程都停留在fork函數(shù)中等待返回,因此會(huì)返回兩次,一個(gè)是在父進(jìn)程中返回,一次是在子進(jìn)程中返回,兩次返回值是不一樣的。

        • 在父進(jìn)程中將返回新建子進(jìn)程的進(jìn)程ID
        • 在子進(jìn)程中將返回0
        • 若出現(xiàn)錯(cuò)誤則返回一個(gè)負(fù)數(shù)

        因此可以通過(guò)fork的返回值來(lái)判斷當(dāng)前進(jìn)程是子進(jìn)程還是父進(jìn)程。

        「fork執(zhí)行執(zhí)行流程」

        當(dāng)進(jìn)程調(diào)用fork后控制轉(zhuǎn)入內(nèi)核,內(nèi)核將會(huì)做4件事兒:

        1. 分配新的內(nèi)存塊和內(nèi)核數(shù)據(jù)結(jié)構(gòu)給子進(jìn)程
        2. 將父進(jìn)程部分?jǐn)?shù)據(jù)結(jié)構(gòu)內(nèi)容(數(shù)據(jù)空間、堆棧等)拷貝到子進(jìn)程
        3. 添加子進(jìn)程到系統(tǒng)進(jìn)程列表中
        4. fork返回開始調(diào)度器調(diào)度

        「為什么pid在父子進(jìn)程中不同呢?」

        其實(shí)就相當(dāng)于鏈表,進(jìn)程形成了鏈表,父進(jìn)程的pid指向子進(jìn)程的進(jìn)程ID,因此子進(jìn)程沒(méi)有子進(jìn)程,所以PID為0,這里的pid相當(dāng)于鏈表中的指針。

        設(shè)備管理

        磁盤調(diào)度算法

        讀寫一個(gè)磁盤塊的時(shí)間的影響因素有:

        • 旋轉(zhuǎn)時(shí)間
        • 尋道時(shí)間實(shí)際的數(shù)據(jù)傳輸時(shí)間

        其中,尋道時(shí)間最長(zhǎng),因此磁盤調(diào)度的主要目標(biāo)是使磁盤的平均尋道時(shí)間最短。

        ?

        先來(lái)先服務(wù) FCFS, First Come First Served

        ?

        按照磁盤請(qǐng)求的順序進(jìn)行調(diào)度,優(yōu)點(diǎn)是公平和簡(jiǎn)單,缺點(diǎn)也很明顯,因?yàn)槲磳?duì)尋道做任何優(yōu)化,使平均尋道時(shí)間可能較長(zhǎng)。

        ?

        最短尋道時(shí)間優(yōu)先,SSTF, Shortest Seek Time First

        ?

        優(yōu)先調(diào)度與當(dāng)前磁頭所在磁道距離最近的磁道, 雖然平均尋道時(shí)間比較低,但是不夠公平,如果新到達(dá)的磁道請(qǐng)求總是比一個(gè)在等待的磁道請(qǐng)求近,那么在等待的 磁道請(qǐng)求會(huì)一直等待下去,也就是出現(xiàn)饑餓現(xiàn)象,具體來(lái)說(shuō),兩邊的磁道請(qǐng)求更容易出現(xiàn)饑餓現(xiàn)象。

        ?

        電梯算法,SCAN

        ?

        電梯總是保持一個(gè)方向運(yùn)行,直到該方向沒(méi)有請(qǐng)求為止,然后改變運(yùn)行方向, 電梯算法(掃描算法)和電梯的運(yùn)行過(guò)程類似,總是按一個(gè)方向來(lái)進(jìn)行磁盤調(diào)度,直到該方向上沒(méi)有未完成的磁盤 請(qǐng)求,然后改變方向,因?yàn)榭紤]了移動(dòng)方向,因此所有的磁盤請(qǐng)求都會(huì)被滿足,解決了 SSTF 的饑餓問(wèn)題

        內(nèi)存管理

        「邏輯地址和物理地址」

        我們編程一般只有可能和邏輯地址打交道,比如在 C 語(yǔ)言中,指針里面存儲(chǔ)的數(shù)值就可以理解成為內(nèi)存里的一個(gè)地址,這個(gè)地址也就是我們說(shuō)的邏輯地址,邏輯地址由操作系統(tǒng)決定。

        物理地址指的是真實(shí)物理內(nèi)存中地址,更具體一點(diǎn)來(lái)說(shuō)就是內(nèi)存地址寄存器中的地址,物理地址是內(nèi)存單元真正的地址。

        編譯時(shí)只需確定變量x存放的相對(duì)地址是100 ( 也就是說(shuō)相對(duì)于進(jìn)程在內(nèi)存中的起始地址而言的地址)。

        CPU想要找到x在內(nèi)存中的實(shí)際存放位置,只需要用進(jìn)程的起始地址+100即可。

        相對(duì)地址又稱邏輯地址,絕對(duì)地址又稱物理地址。

        「內(nèi)存管理有哪幾種方式」

        1. 「塊式管理」:將內(nèi)存分為幾個(gè)固定大小的塊,每個(gè)塊中只包含一個(gè)進(jìn)程,如果程序運(yùn)行需要內(nèi)存的話,操作系統(tǒng)就分配給它一塊,如果程序運(yùn)行只需要很小的空間的話,分配的這塊內(nèi)存很大一部分幾乎被浪費(fèi)了,這些在每個(gè)塊中未被利用的空間,我們稱之為碎片。
        2. 「頁(yè)式管理」:把主存分為大小相等且固定的一頁(yè)一頁(yè)的形式,頁(yè)較小,相對(duì)相比于塊式管理的劃分力度更大,提高了內(nèi)存利用率,減少了碎片,頁(yè)式管理通過(guò)頁(yè)表對(duì)應(yīng)邏輯地址和物理地址。
        1. 「段式管理」: 頁(yè)式管理雖然提高了內(nèi)存利用率,但是頁(yè)式管理其中的頁(yè)實(shí)際并無(wú)任何實(shí)際意義, 段式管理把主存分為一段段的,每一段的空間又要比一頁(yè)的空間小很多 ,段式管理通過(guò)段表對(duì)應(yīng)邏輯地址和物理地址。
        2. 「段頁(yè)式管理機(jī)制:「段頁(yè)式管理機(jī)制結(jié)合了段式管理和頁(yè)式管理的優(yōu)點(diǎn),簡(jiǎn)單來(lái)說(shuō)段頁(yè)式管理機(jī)制就是把主存先分成若干段,每個(gè)段又分成若干頁(yè),也就是說(shuō)」段頁(yè)式管理機(jī)制」中段與段之間以及段的內(nèi)部的都是離散的。

        虛擬地址

        現(xiàn)代處理器使用的是一種稱為**虛擬尋址(Virtual Addressing)**的尋址方式

        「使用虛擬尋址,CPU 需要將虛擬地址翻譯成物理地址,這樣才能訪問(wèn)到真實(shí)的物理內(nèi)存?!?/strong>

        實(shí)際上完成虛擬地址轉(zhuǎn)換為物理地址轉(zhuǎn)換的硬件是 CPU 中含有一個(gè)被稱為**內(nèi)存管理單元(Memory Management Unit, MMU)**的硬件

        「為什么要有虛擬地址空間」

        沒(méi)有虛擬地址空間的時(shí)候,「程序都是直接訪問(wèn)和操作的都是物理內(nèi)存」。

        但是這樣有什么問(wèn)題?

        1. 用戶程序可以訪問(wèn)任意內(nèi)存,尋址內(nèi)存的每個(gè)字節(jié),這樣就很容易破壞操作系統(tǒng),造成操作系統(tǒng)崩潰。
        2. 想要同時(shí)運(yùn)行多個(gè)程序特別困難,比如你想同時(shí)運(yùn)行一個(gè)微信和一個(gè) QQ 音樂(lè)都不行,為什么呢?舉個(gè)簡(jiǎn)單的例子:微信在運(yùn)行的時(shí)候給內(nèi)存地址 1xxx 賦值后,QQ 音樂(lè)也同樣給內(nèi)存地址 1xxx 賦值,那么 QQ 音樂(lè)對(duì)內(nèi)存的賦值就會(huì)覆蓋微信之前所賦的值,這就造成了微信這個(gè)程序就會(huì)崩潰。

        「通過(guò)虛擬地址訪問(wèn)內(nèi)存有以下優(yōu)勢(shì):」

        • 程序可以使用一系列相鄰的虛擬地址來(lái)訪問(wèn)物理內(nèi)存中不相鄰的大內(nèi)存緩沖區(qū)。
        • 程序可以使用一系列虛擬地址來(lái)訪問(wèn)大于可用物理內(nèi)存的內(nèi)存緩沖區(qū)。
        • 不同進(jìn)程使用的虛擬地址彼此隔離,一個(gè)進(jìn)程中的代碼無(wú)法更改正在由另一進(jìn)程或操作系統(tǒng)使用的物理內(nèi)存。

        「MMU如何把虛擬地址翻譯成物理地址的」

        對(duì)于每個(gè)程序,內(nèi)存管理單元MMU都為其保存一個(gè)頁(yè)表,該頁(yè)表中存放的是虛擬頁(yè)面到物理頁(yè)面的映射。

        每當(dāng)為一個(gè)虛擬頁(yè)面尋找到一個(gè)物理頁(yè)面之后,就在頁(yè)表里增加一條記錄來(lái)保留該映射關(guān)系,當(dāng)然,隨著虛擬頁(yè)面進(jìn)出物理內(nèi)存,頁(yè)表的內(nèi)容也會(huì)不斷更新變化。

        虛擬內(nèi)存

        很多時(shí)候我們使用點(diǎn)開了很多占內(nèi)存的軟件,這些軟件占用的內(nèi)存可能已經(jīng)遠(yuǎn)遠(yuǎn)超出了我們電腦本身具有的物理內(nèi)存

        通過(guò) 「虛擬內(nèi)存」 可以讓程序可以擁有超過(guò)系統(tǒng)物理內(nèi)存大小的可用內(nèi)存空間。

        另外,虛擬內(nèi)存為每個(gè)進(jìn)程提供了一個(gè)一致的、私有的地址空間,它讓每個(gè)進(jìn)程產(chǎn)生了一種自己在獨(dú)享主存的錯(cuò)覺(jué)(每個(gè)進(jìn)程擁有一片連續(xù)完整的內(nèi)存空間),這樣會(huì)更加有效地管理內(nèi)存并減少出錯(cuò)。

        「虛擬內(nèi)存」是計(jì)算機(jī)系統(tǒng)內(nèi)存管理的一種技術(shù),我們可以手動(dòng)設(shè)置自己電腦的虛擬內(nèi)存

        「虛擬內(nèi)存的重要意義是它定義了一個(gè)連續(xù)的虛擬地址空間」,并且 「把內(nèi)存擴(kuò)展到硬盤空間」

        「虛擬內(nèi)存的實(shí)現(xiàn)有以下三種方式:」

        1. 「請(qǐng)求分頁(yè)存儲(chǔ)管理」 :請(qǐng)求分頁(yè)是目前最常用的一種實(shí)現(xiàn)虛擬存儲(chǔ)器的方法,請(qǐng)求分頁(yè)存儲(chǔ)管理系統(tǒng)中,在作業(yè)開始運(yùn)行之前,僅裝入當(dāng)前要執(zhí)行的部分段即可運(yùn)行,假如在作業(yè)運(yùn)行的過(guò)程中發(fā)現(xiàn)要訪問(wèn)的頁(yè)面不在內(nèi)存,則由處理器通知操作系統(tǒng)按照對(duì)應(yīng)的頁(yè)面置換算法將相應(yīng)的頁(yè)面調(diào)入到主存,同時(shí)操作系統(tǒng)也可以將暫時(shí)不用的頁(yè)面置換到外存中。
        2. 「請(qǐng)求分段存儲(chǔ)管理」 :請(qǐng)求分段儲(chǔ)存管理方式就如同請(qǐng)求分頁(yè)儲(chǔ)存管理方式一樣,在作業(yè)開始運(yùn)行之前,僅裝入當(dāng)前要執(zhí)行的部分段即可運(yùn)行;在執(zhí)行過(guò)程中,可使用請(qǐng)求調(diào)入中斷動(dòng)態(tài)裝入要訪問(wèn)但又不在內(nèi)存的程序段;當(dāng)內(nèi)存空間已滿,而又需要裝入新的段時(shí),根據(jù)置換功能適當(dāng)調(diào)出某個(gè)段,以便騰出空間而裝入新的段。
        3. 「請(qǐng)求段頁(yè)式存儲(chǔ)管理」

        不管是上面那種實(shí)現(xiàn)方式,我們一般都需要:

        ?

        一定容量的內(nèi)存和外存:在載入程序的時(shí)候,只需要將程序的一部分裝入內(nèi)存,而將其他部分留在外存,然后程序就可以執(zhí)行了;

        ?

        缺頁(yè)中斷

        如果「需執(zhí)行的指令或訪問(wèn)的數(shù)據(jù)尚未在內(nèi)存」(稱為缺頁(yè)或缺段),則由處理器通知操作系統(tǒng)將相應(yīng)的頁(yè)面或段「調(diào)入到內(nèi)存」,然后繼續(xù)執(zhí)行程序;

        在分頁(yè)系統(tǒng)中,一個(gè)虛擬頁(yè)面既有可能在物理內(nèi)存,也有可能保存在磁盤上。

        如果CPU發(fā)出的虛擬地址對(duì)應(yīng)的頁(yè)面不在物理內(nèi)存,就將產(chǎn)生一個(gè)缺頁(yè)中斷,而缺頁(yè)中斷服務(wù)程序負(fù)責(zé)將需要的虛擬頁(yè)面找到并加載到內(nèi)存。

        缺頁(yè)中斷的處理步驟如下,省略了中間很多的步驟,只保留最核心的幾個(gè)步驟:

        頁(yè)面置換算法

        當(dāng)發(fā)生缺頁(yè)中斷時(shí),如果當(dāng)前內(nèi)存中并沒(méi)有空閑的頁(yè)面,操作系統(tǒng)就必須在內(nèi)存選擇一個(gè)頁(yè)面將其移出內(nèi)存,以便為即將調(diào)入的頁(yè)面讓出空間。

        用來(lái)選擇淘汰哪一頁(yè)的規(guī)則叫做頁(yè)面置換算法,我們可以把頁(yè)面置換算法看成是淘汰頁(yè)面的規(guī)則

        • 「OPT 頁(yè)面置換算法(最佳頁(yè)面置換算法)」 :該置換算法所選擇的被淘汰頁(yè)面將是以后永不使用的,或者是在最長(zhǎng)時(shí)間內(nèi)不再被訪問(wèn)的頁(yè)面,這樣可以保證獲得最低的缺頁(yè)率,但由于人們目前無(wú)法預(yù)知進(jìn)程在內(nèi)存下的若千頁(yè)面中哪個(gè)是未來(lái)最長(zhǎng)時(shí)間內(nèi)不再被訪問(wèn)的,因而該算法無(wú)法實(shí)現(xiàn),一般作為衡量其他置換算法的方法。

        • 「FIFO(First In First Out) 頁(yè)面置換算法(先進(jìn)先出頁(yè)面置換算法)」 : 總是淘汰最先進(jìn)入內(nèi)存的頁(yè)面,即選擇在內(nèi)存中駐留時(shí)間最久的頁(yè)面進(jìn)行淘汰。

        • 「LRU (Least Currently Used)頁(yè)面置換算法(最近最久未使用頁(yè)面置換算法)」 :LRU算法賦予每個(gè)頁(yè)面一個(gè)訪問(wèn)字段,用來(lái)記錄一個(gè)頁(yè)面自上次被訪問(wèn)以來(lái)所經(jīng)歷的時(shí)間 T,當(dāng)須淘汰一個(gè)頁(yè)面時(shí),選擇現(xiàn)有頁(yè)面中其 T 值最大的,即最近最久未使用的頁(yè)面予以淘汰。

        • 「LFU (Least Frequently Used)頁(yè)面置換算法(最少使用頁(yè)面置換算法)」 : 該置換算法選擇在之前時(shí)期使用最少的頁(yè)面作為淘汰頁(yè)。

        局部性原理

        局部性原理是虛擬內(nèi)存技術(shù)的基礎(chǔ),正是因?yàn)槌绦蜻\(yùn)行具有局部性原理,才可以只裝入部分程序到內(nèi)存就開始運(yùn)行。

        局部性原理表現(xiàn)在以下兩個(gè)方面:

        1. 「時(shí)間局部性」 :如果程序中的某條指令一旦執(zhí)行,不久以后該指令可能再次執(zhí)行;如果某數(shù)據(jù)被訪問(wèn)過(guò),不久以后該數(shù)據(jù)可能再次被訪問(wèn),產(chǎn)生時(shí)間局部性的典型原因,是由于在程序中存在著大量的循環(huán)操作。
        2. 「空間局部性」 :一旦程序訪問(wèn)了某個(gè)存儲(chǔ)單元,在不久之后,其附近的存儲(chǔ)單元也將被訪問(wèn),即程序在一段時(shí)間內(nèi)所訪問(wèn)的地址,可能集中在一定的范圍之內(nèi),這是因?yàn)橹噶钔ǔJ琼樞虼娣?、順序?zhí)行的,數(shù)據(jù)也一般是以向量、數(shù)組、表等形式簇聚存儲(chǔ)的。

        時(shí)間局部性是通過(guò)將近來(lái)使用的指令和數(shù)據(jù)保存到「高速緩存存儲(chǔ)器」中,并使用高速緩存的層次結(jié)構(gòu)實(shí)現(xiàn)。

        空間局部性通常是使用較大的高速緩存,并將預(yù)取機(jī)制集成到高速緩存控制邏輯中實(shí)現(xiàn)。

        頁(yè)表

        操作系統(tǒng)將虛擬內(nèi)存分塊,每個(gè)小塊稱為一個(gè)頁(yè)(Page);真實(shí)內(nèi)存也需要分塊,每個(gè)小塊我們稱為一個(gè) Frame。

        Page 到 Frame 的映射,需要一種叫作頁(yè)表的結(jié)構(gòu)。

        上圖展示了 Page、Frame 和頁(yè)表 (PageTable)三者之間的關(guān)系。

        Page 大小和 Frame 大小通常相等,頁(yè)表中記錄的某個(gè) Page 對(duì)應(yīng)的 Frame 編號(hào)。

        頁(yè)表也需要存儲(chǔ)空間,比如虛擬內(nèi)存大小為 10G, Page 大小是 4K,那么需要 10G/4K = 2621440 個(gè)條目。

        如果每個(gè)條目是 64bit,那么一共需要 20480K = 20M 頁(yè)表,操作系統(tǒng)在內(nèi)存中劃分出小塊區(qū)域給頁(yè)表,并負(fù)責(zé)維護(hù)頁(yè)表。

        「頁(yè)表維護(hù)了虛擬地址到真實(shí)地址的映射?!?/strong>

        每次程序使用內(nèi)存時(shí),需要把虛擬內(nèi)存地址換算成物理內(nèi)存地址,換算過(guò)程分為以下 3 個(gè)步驟:

        • 通過(guò)虛擬地址計(jì)算 Page 編號(hào);

        • 查頁(yè)表,根據(jù) Page 編號(hào),找到 Frame 編號(hào);

        • 將虛擬地址換算成物理地址。

        多級(jí)頁(yè)表

        引入多級(jí)頁(yè)表的主要目的是為了避免把全部頁(yè)表一直放在內(nèi)存中占用過(guò)多空間,特別是那些根本就不需要的頁(yè)表就不需要保留在內(nèi)存中

        「一級(jí)頁(yè)表:」

        假如物理內(nèi)存中一共有1048576個(gè)頁(yè),那么頁(yè)表就需要總共就是1048576 * 4B = 4M

        也就是說(shuō)我需要4M連續(xù)的內(nèi)存來(lái)存放這個(gè)頁(yè)表,也就是一級(jí)頁(yè)表。

        隨著虛擬地址空間的增大,存放頁(yè)表所需要的連續(xù)空間也會(huì)增大,在操作系統(tǒng)內(nèi)存緊張或者內(nèi)存碎片較多時(shí),這無(wú)疑會(huì)帶來(lái)額外的開銷。

        頁(yè)表尋址是用寄存器來(lái)確定一級(jí)頁(yè)表地址的,所以一級(jí)頁(yè)表的地址必須指向確定的物理頁(yè),否則就會(huì)出現(xiàn)錯(cuò)誤,所以如果用一級(jí)頁(yè)表的話,就必須把全部的頁(yè)表都加載進(jìn)去。

        「二級(jí)頁(yè)表:」

        而使用二級(jí)頁(yè)表的話,只需要加載一個(gè)頁(yè)目錄表(一級(jí)頁(yè)表),大小為4K,可以管理1024個(gè)二級(jí)頁(yè)表。

        可能你會(huì)有疑問(wèn),這1024個(gè)二級(jí)頁(yè)表也是需要內(nèi)存空間的,這下反而需要4MB+4KB的內(nèi)存,反而更多了。

        其實(shí)二級(jí)頁(yè)表并不是一定要存在內(nèi)存中的,內(nèi)存中只需要一個(gè)一級(jí)頁(yè)表地址存在存器即可,二級(jí)頁(yè)表可以使用缺頁(yè)中斷從外存移入內(nèi)存。

        「多級(jí)頁(yè)表屬于時(shí)間換空間的典型場(chǎng)景」

        快表

        為了解決虛擬地址到物理地址的轉(zhuǎn)換速度,操作系統(tǒng)在「頁(yè)表方案」基礎(chǔ)之上引入了「快表」來(lái)加速虛擬地址到物理地址的轉(zhuǎn)換

        我們可以把快表理解為一種特殊的「高速緩沖存儲(chǔ)器(Cache)」,其中的內(nèi)容是頁(yè)表的一部分或者全部?jī)?nèi)容,作為頁(yè)表的 Cache,它的作用與頁(yè)表相似,但是提高了訪問(wèn)速率,由于采用頁(yè)表做地址轉(zhuǎn)換,讀寫內(nèi)存數(shù)據(jù)時(shí) CPU 要訪問(wèn)兩次主存,有了快表,有時(shí)只要訪問(wèn)一次高速緩沖存儲(chǔ)器,一次主存,這樣可加速查找并提高指令執(zhí)行速度。

        「使用快表之后的地址轉(zhuǎn)換流程是這樣的:」

        1. 根據(jù)虛擬地址中的頁(yè)號(hào)查快表;
        2. 如果該頁(yè)在快表中,直接從快表中讀取相應(yīng)的物理地址;
        3. 如果該頁(yè)不在快表中,就訪問(wèn)內(nèi)存中的頁(yè)表,再?gòu)捻?yè)表中得到物理地址,同時(shí)將頁(yè)表中的該映射表項(xiàng)添加到快表中;
        4. 當(dāng)快表填滿后,又要登記新頁(yè)時(shí),就按照一定的淘汰策略淘汰掉快表中的一個(gè)頁(yè)。

        內(nèi)存管理單元

        在 CPU 中一個(gè)小型的設(shè)備——內(nèi)存管理單元(MMU)

        當(dāng) CPU 需要執(zhí)行一條指令時(shí),如果指令中涉及內(nèi)存讀寫操作,CPU 會(huì)把虛擬地址給 MMU,MMU 自動(dòng)完成虛擬地址到真實(shí)地址的計(jì)算;然后,MMU 連接了地址總線,幫助 CPU 操作真實(shí)地址。

        在不同 CPU 的 MMU 可能是不同的,因此這里會(huì)遇到很多跨平臺(tái)的問(wèn)題。

        解決跨平臺(tái)問(wèn)題不但有繁重的工作量,更需要高超的編程技巧。

        動(dòng)態(tài)分區(qū)分配算法

        內(nèi)存分配算法,大體來(lái)說(shuō)分為:「連續(xù)式分配 與 非連續(xù)式分配」

        連續(xù)式分配就是把所以要執(zhí)行的程序 「完整的,有序的」 存入內(nèi)存,連續(xù)式分配又可以分為「固定分區(qū)分配 和 動(dòng)態(tài)分區(qū)分配」

        非連續(xù)式分配就是把要執(zhí)行的程序按照一定規(guī)則進(jìn)行拆分,顯然這樣更有效率,現(xiàn)在的操作系統(tǒng)通常也都是采用這種方式分配內(nèi)存

        所謂動(dòng)態(tài)分區(qū)分配,就是指「內(nèi)存在初始時(shí)不會(huì)劃分區(qū)域,而是會(huì)在進(jìn)程裝入時(shí),根據(jù)所要裝入的進(jìn)程大小動(dòng)態(tài)地對(duì)內(nèi)存空間進(jìn)行劃分,以提高內(nèi)存空間利用率,降低碎片的大小」

        動(dòng)態(tài)分區(qū)分配算法有以下四種:

        ?

        首次適應(yīng)算法(First Fit)

        ?

        空閑分區(qū)以地址遞增的次序鏈接,分配內(nèi)存時(shí)順序查找,找到大小滿足要求的第一個(gè)空閑分區(qū)就進(jìn)行分配

        ?

        鄰近適應(yīng)算法(Next Fit)

        ?

        又稱循環(huán)首次適應(yīng)法,由首次適應(yīng)法演變而成,不同之處是分配內(nèi)存時(shí)從上一次查找結(jié)束的位置開始繼續(xù)查找

        ?

        最佳適應(yīng)算法(Best Fit)

        ?

        空閑分區(qū)按容量遞增形成分區(qū)鏈,找到第一個(gè)能滿足要求的空閑分區(qū)就進(jìn)行分配

        ?

        最壞適應(yīng)算法(Next Fit)

        ?

        又稱最大適應(yīng)算法,空閑分區(qū)以容量遞減的次序鏈接,找到第一個(gè)能滿足要求的空閑分區(qū)(也就是最大的分區(qū))就進(jìn)行分配

        「總結(jié)」

        首次適應(yīng)不僅最簡(jiǎn)單,通常也是最好最快,不過(guò)首次適應(yīng)算法會(huì)使得內(nèi)存低地址部分出現(xiàn)很多小的空閑分區(qū),而每次查找都要經(jīng)過(guò)這些分區(qū),因此也增加了查找的開銷。

        鄰近算法試圖解決這個(gè)問(wèn)題,但實(shí)際上,它常常會(huì)導(dǎo)致在內(nèi)存的末尾分配空間分裂成小的碎片,它通常比首次適應(yīng)算法結(jié)果要差。

        最佳適應(yīng)算法導(dǎo)致大量碎片,最壞適應(yīng)算法導(dǎo)致沒(méi)有大的空間。

        內(nèi)存覆蓋

        覆蓋與交換技術(shù)是在程序用來(lái)擴(kuò)充內(nèi)存的兩種方法。

        早期的計(jì)算機(jī)系統(tǒng)中,主存容量很小,雖然主存中僅存放一道用戶程序,但是存儲(chǔ)空間放不下用戶進(jìn)程的現(xiàn)象也經(jīng)常發(fā)生,這一矛盾可以用覆蓋技術(shù)來(lái)解決。

        「覆蓋的基本思想是:」

        由于程序運(yùn)行時(shí)并非任何時(shí)候都要訪問(wèn)程序及數(shù)據(jù)的各個(gè)部分(尤其是大程序),因此可以把用戶空間分成一個(gè)固定區(qū)和若干個(gè)覆蓋區(qū)。

        將經(jīng)?;钴S的部分放在固定區(qū),其余部分按調(diào)用關(guān)系分段。

        首先將那些即將要訪問(wèn)的段放入覆蓋區(qū),其他段放在外存中,在需要調(diào)用前,系統(tǒng)再將其調(diào)入覆蓋區(qū),替換覆蓋區(qū)中原有的段。

        覆蓋技術(shù)的特點(diǎn)是打破了必須將一個(gè)進(jìn)程的全部信息裝入主存后才能運(yùn)行的限制,但當(dāng)同時(shí)運(yùn)行程序的代碼量大于主存時(shí)仍不能運(yùn)行。

        內(nèi)存交換

        「交換的基本思想」

        把處于等待狀態(tài)(或在CPU調(diào)度原則下被剝奪運(yùn)行權(quán)利)的程序從內(nèi)存移到輔存,把內(nèi)存空間騰出來(lái),這一過(guò)程又叫換出;

        把準(zhǔn)備好競(jìng)爭(zhēng)CPU運(yùn)行的程序從輔存移到內(nèi)存,這一過(guò)程又稱為換入。

        ?

        例如,有一個(gè)CPU釆用時(shí)間片輪轉(zhuǎn)調(diào)度算法的多道程序環(huán)境。

        ?

        時(shí)間片到,內(nèi)存管理器將剛剛執(zhí)行過(guò)的進(jìn)程換出,將另一進(jìn)程換入到剛剛釋放的內(nèi)存空間中。

        同時(shí),CPU調(diào)度器可以將時(shí)間片分配給其他已在內(nèi)存中的進(jìn)程。

        每個(gè)進(jìn)程用完時(shí)間片都與另一進(jìn)程交換。

        理想情況下,內(nèi)存管理器的交換過(guò)程速度足夠快,總有進(jìn)程在內(nèi)存中可以執(zhí)行。

        ?

        交換技術(shù)主要是在不同進(jìn)程(或作業(yè))之間進(jìn)行,而覆蓋則用于同一個(gè)程序或進(jìn)程中。

        ?

        由于覆蓋技術(shù)要求給出程序段之間的覆蓋結(jié)構(gòu),使得其對(duì)用戶和程序員不透明,所以對(duì)于主存無(wú)法存放用戶程序的矛盾

        現(xiàn)代操作系統(tǒng)是通過(guò)虛擬內(nèi)存技術(shù)來(lái)解決的,覆蓋技術(shù)則已成為歷史;而交換技術(shù)在現(xiàn)代操作系統(tǒng)中仍具有較強(qiáng)的生命力。

        常見面試題

        「進(jìn)程、線程的區(qū)別」

        操作系統(tǒng)會(huì)以進(jìn)程為單位,分配系統(tǒng)資源(CPU時(shí)間片、內(nèi)存等資源),進(jìn)程是資源分配的最小單位。

        調(diào)度:線程作為CPU調(diào)度和分配的基本單位,進(jìn)程作為擁有資源的基本單位;

        并發(fā)性:不僅進(jìn)程之間可以并發(fā)執(zhí)行,同一個(gè)進(jìn)程的多個(gè)線程之間也可并發(fā)執(zhí)行;

        ?

        擁有資源:

        ?

        進(jìn)程是擁有資源的一個(gè)獨(dú)立單位,線程不擁有系統(tǒng)資源,但可以訪問(wèn)隸屬于進(jìn)程的資源。

        進(jìn)程所維護(hù)的是程序所包含的資源(靜態(tài)資源), 如:地址空間,打開的文件句柄集,文件系統(tǒng)狀態(tài),信號(hào)處理handler等;

        線程所維護(hù)的運(yùn)行相關(guān)的資源(動(dòng)態(tài)資源),如:運(yùn)行棧,調(diào)度相關(guān)的控制信息,待處理的信號(hào)集等;

        ?

        系統(tǒng)開銷:

        ?

        在創(chuàng)建或撤消進(jìn)程時(shí),由于系統(tǒng)都要為之分配和回收資源,導(dǎo)致系統(tǒng)的開銷明顯大于創(chuàng)建或撤消線程時(shí)的開銷。

        但是進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響,而線程只是一個(gè)進(jìn)程中的不同執(zhí)行路徑。

        線程有自己的堆棧和局部變量,但線程之間沒(méi)有單獨(dú)的地址空間,一個(gè)進(jìn)程死掉就等于所有的線程死掉,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時(shí),耗費(fèi)資源較大,效率要差一些。

        「一個(gè)進(jìn)程可以創(chuàng)建多少線程」

        理論上,一個(gè)進(jìn)程可用虛擬空間是2G,默認(rèn)情況下,線程的棧的大小是1MB,所以理論上最多只能創(chuàng)建2048個(gè)線程。

        如果要?jiǎng)?chuàng)建多于2048的話,必須修改編譯器的設(shè)置。

        在一般情況下,你不需要那么多的線程,過(guò)多的線程將會(huì)導(dǎo)致大量的時(shí)間浪費(fèi)在線程切換上,給程序運(yùn)行效率帶來(lái)負(fù)面影響。

        「外中斷和異常有什么區(qū)別」

        外中斷是指由 CPU 執(zhí)行指令以外的事件引起,如 I/O 完成中斷,表示設(shè)備輸入/輸出處理已經(jīng)完成,處理器能夠發(fā)送下一個(gè)輸入/輸出請(qǐng)求,此外還有時(shí)鐘中斷、控制臺(tái)中斷等。

        而異常時(shí)由 CPU 執(zhí)行指令的內(nèi)部事件引起,如非法操作碼、地址越界、算術(shù)溢出等。

        「解決Hash沖突四種方法」

        開放定址法

        • 開放定址法就是一旦發(fā)生了沖突,就去尋找下一個(gè)空的散列地址,只要散列表足夠大,空的散列地址總能找到,并將記錄存入。

        鏈地址法

        • 將哈希表的每個(gè)單元作為鏈表的頭結(jié)點(diǎn),所有哈希地址為i的元素構(gòu)成一個(gè)同義詞鏈表。即發(fā)生沖突時(shí)就把該關(guān)鍵字鏈在以該單元為頭結(jié)點(diǎn)的鏈表的尾部。

        再哈希法

        • 當(dāng)哈希地址發(fā)生沖突用其他的函數(shù)計(jì)算另一個(gè)哈希函數(shù)地址,直到?jīng)_突不再產(chǎn)生為止。

        建立公共溢出區(qū)

        • 將哈希表分為基本表和溢出表兩部分,發(fā)生沖突的元素都放入溢出表中。

        「分頁(yè)機(jī)制和分段機(jī)制有哪些共同點(diǎn)和區(qū)別」

        共同點(diǎn)

        • 分頁(yè)機(jī)制和分段機(jī)制都是為了提高內(nèi)存利用率,較少內(nèi)存碎片。
        • 頁(yè)和段都是離散存儲(chǔ)的,所以兩者都是離散分配內(nèi)存的方式。但是,每個(gè)頁(yè)和段中的內(nèi)存是連續(xù)的。

        區(qū)別

        • 頁(yè)的大小是固定的,由操作系統(tǒng)決定;而段的大小不固定,取決于我們當(dāng)前運(yùn)行的程序。
        • 分頁(yè)僅僅是為了滿足操作系統(tǒng)內(nèi)存管理的需求,而段是邏輯信息的單位,在程序中可以體現(xiàn)為代碼段,數(shù)據(jù)段,能夠更好滿足用戶的需要。
        • 分頁(yè)是一維地址空間,分段是二維的。

        「介紹一下幾種典型的鎖」

        ?

        讀寫鎖

        ?
        • 可以同時(shí)進(jìn)行多個(gè)讀
        • 寫者必須互斥(只允許一個(gè)寫者寫,也不能讀者寫者同時(shí)進(jìn)行)
        • 寫者優(yōu)先于讀者(一旦有寫者,則后續(xù)讀者必須等待,喚醒時(shí)優(yōu)先考慮寫者)
        ?

        互斥鎖

        ?

        一次只能一個(gè)線程擁有互斥鎖,其他線程只有等待

        互斥鎖是在搶鎖失敗的情況下主動(dòng)放棄CPU進(jìn)入睡眠狀態(tài)直到鎖的狀態(tài)改變時(shí)再喚醒,而操作系統(tǒng)負(fù)責(zé)線程調(diào)度,為了實(shí)現(xiàn)鎖的狀態(tài)發(fā)生改變時(shí)喚醒阻塞的線程或者進(jìn)程,需要把鎖交給操作系統(tǒng)管理,所以互斥鎖在加鎖操作時(shí)涉及上下文的切換。

        互斥鎖實(shí)際的效率還是可以讓人接受的,加鎖的時(shí)間大概100ns左右,而實(shí)際上互斥鎖的一種可能的實(shí)現(xiàn)是先自旋一段時(shí)間,當(dāng)自旋的時(shí)間超過(guò)閥值之后再將線程投入睡眠中,因此在并發(fā)運(yùn)算中使用互斥鎖(每次占用鎖的時(shí)間很短)的效果可能不亞于使用自旋鎖

        ?

        條件變量

        ?

        互斥鎖一個(gè)明顯的缺點(diǎn)是他只有兩種狀態(tài):鎖定和非鎖定。

        而條件變量通過(guò)允許線程阻塞和等待另一個(gè)線程發(fā)送信號(hào)的方法彌補(bǔ)了互斥鎖的不足,他常和互斥鎖一起使用,以免出現(xiàn)競(jìng)態(tài)條件。

        當(dāng)條件不滿足時(shí),線程往往解開相應(yīng)的互斥鎖并阻塞線程然后等待條件發(fā)生變化。

        一旦其他的某個(gè)線程改變了條件變量,他將通知相應(yīng)的條件變量喚醒一個(gè)或多個(gè)正被此條件變量阻塞的線程。

        總的來(lái)說(shuō)「互斥鎖是線程間互斥的機(jī)制,條件變量則是同步機(jī)制。」

        ?

        自旋鎖

        ?

        如果進(jìn)線程無(wú)法取得鎖,進(jìn)線程不會(huì)立刻放棄CPU時(shí)間片,而是一直循環(huán)嘗試獲取鎖,直到獲取為止。

        如果別的線程長(zhǎng)時(shí)期占有鎖,那么自旋就是在浪費(fèi)CPU做無(wú)用功,但是自旋鎖一般應(yīng)用于加鎖時(shí)間很短的場(chǎng)景,這個(gè)時(shí)候效率比較高。

        雖然它的效率比互斥鎖高,但是它也有些不足之處:

        • 自旋鎖一直占用CPU,在未獲得鎖的情況下,一直進(jìn)行自旋,所以占用著CPU,如果不能在很短的時(shí)間內(nèi)獲得鎖,無(wú)疑會(huì)使CPU效率降低。
        • 在用自旋鎖時(shí)有可能造成死鎖,當(dāng)遞歸調(diào)用時(shí)有可能造成死鎖。

        「如何讓進(jìn)程后臺(tái)運(yùn)行」

        1.命令后面加上&即可,實(shí)際上,這樣是將命令放入到一個(gè)作業(yè)隊(duì)列中了

        2.ctrl + z 掛起進(jìn)程,使用jobs查看序號(hào),在使用bg %序號(hào)后臺(tái)運(yùn)行進(jìn)程

        3.nohup + &,將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤缺省會(huì)被重定向到 nohup.out 文件中,忽略所有掛斷(SIGHUP)信號(hào)

        nohup ping www.ibm.com &

        4.運(yùn)行指令前面 + setsid,使其父進(jìn)程變成init進(jìn)程,不受SIGHUP信號(hào)的影響

        [root@pvcent107 ~]# setsid ping www.ibm.com
        [root@pvcent107 ~]# ps -ef |grep www.ibm.com
        root     31094     1  0 07:28 ?        00:00:00 ping www.ibm.com
        root     31102 29217  0 07:29 pts/4    00:00:00 grep www.ibm.com

        上例中我們的進(jìn)程 ID(PID)為31094,而它的父 ID(PPID)為1(即為 init 進(jìn)程 ID),并不是當(dāng)前終端的進(jìn)程 ID。

        ?

        5.將命令+ &放在()括號(hào)中,也可以是進(jìn)程不受HUP信號(hào)的影響

        ?
        [root@pvcent107 ~]# (ping www.ibm.com &)

        「異常和中斷的區(qū)別」

        ?

        中斷

        ?

        當(dāng)我們?cè)谇脫翩I盤的同時(shí)就會(huì)產(chǎn)生中斷,當(dāng)硬盤讀寫完數(shù)據(jù)之后也會(huì)產(chǎn)生中斷,所以,我們需要知道,中斷是由硬件設(shè)備產(chǎn)生的,而它們從物理上說(shuō)就是電信號(hào),之后,它們通過(guò)中斷控制器發(fā)送給CPU,接著CPU判斷收到的中斷來(lái)自于哪個(gè)硬件設(shè)備(這定義在內(nèi)核中),最后,由CPU發(fā)送給內(nèi)核,有內(nèi)核處理中斷。

        下面這張圖顯示了中斷處理的流程:

        ?

        異常

        ?

        CPU處理程序的時(shí)候一旦程序不在內(nèi)存中,會(huì)產(chǎn)生缺頁(yè)異常;當(dāng)運(yùn)行除法程序時(shí),當(dāng)除數(shù)為0時(shí),又會(huì)產(chǎn)生除0異常。

        「異常是由CPU產(chǎn)生的,同時(shí),它會(huì)發(fā)送給內(nèi)核,要求內(nèi)核處理這些異常」

        下面這張圖顯示了異常處理的流程:

        ?

        相同點(diǎn)

        ?
        • 最后都是由CPU發(fā)送給內(nèi)核,由內(nèi)核去處理
        • 處理程序的流程設(shè)計(jì)上是相似的
        ?

        不同點(diǎn)

        ?
        • 產(chǎn)生源不相同,異常是由CPU產(chǎn)生的,而中斷是由硬件設(shè)備產(chǎn)生的
        • 內(nèi)核需要根據(jù)是異常還是中斷調(diào)用不同的處理程序
        • 中斷不是時(shí)鐘同步的,這意味著中斷可能隨時(shí)到來(lái);異常由于是CPU產(chǎn)生的,所以它是時(shí)鐘同步的
        • 當(dāng)處理中斷時(shí),處于中斷上下文中;處理異常時(shí),處于進(jìn)程上下文中


        瀏覽 40
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

          <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产成人午夜高潮毛片| 午夜精品久久久久久久| 青青草成人网站| 男女AV网站| 无码在线视频播放| 69成人精品视频| 免费播放片色情A片| 在线激情| 99免费观看视频| 中国老女人性爱视频| 日本人妻在线观看| 欧美V在线| 国产无遮挡又黄又爽在线观看| 亚洲天堂影院| 一级爱爱免费视频| 久久久久无码精品亚洲日韩| 久久99久久99精品免视看婷婷| 欧美1区2区| www免费视频| 国产精品色情A级毛片| 开心激情播播网| 逼特逼| 91久久国产| 天天爽天天射| 琪琪色在线视频| 成人动漫在线观看| 日韩操屄视频| 无码中文一区| 秋霞丝鲁片一区二区三区手机在绒免| 亚洲黄色成人网站| 波多野成人无码精品视频| 蜜臀久久99久久久久久宅男| 免费看a的网站| 欧美日逼小视频| 中文字幕乱伦| 中文字幕在线观看网站| 99在线视频免费观看| 欧美一区二区三曲的| 亚洲无码在线视频播放| 91视频中文字幕| www免费视频在线观看播放| 天天草av| 成年人黄色在线观看| www.av免费| xxxx国产| 国产性爱网址| 午夜福利10000| 先锋成人AV| 亚洲.欧美.丝袜.中文.综合 | 在线观看免费黄色视频| 免费毛片网址| 一二区无码| 亚洲天堂影音先锋| 日韩日韩日韩日韩日韩| 色呦呦视频| 韩国午夜福利视频| 人成免费网站| 插菊花综合| 成人免费无码婬片在线| 91精品视频在线播放| 欧美日逼网站| 新妺妺窝窝777777野外| 中文字幕aV在线| 亚洲在线中文| 亚洲日韩欧美色图| 玖玖色视频| 久久久久久久久免费视频| 嫩BBB槡BBBB槡BBB小号| 一级二级无码| 人妻丝袜中出北条麻妃| 亚洲欧美日韩黑料吃瓜在线观看| 亚洲v| 日韩人妻无码一区二区三区99| 亚洲AV无码成人精品国产五月天| 色欲av伊人久久大香线蕉影院| 国产综合网站| 国产精品国产三级国产AⅤ原创| 激情五月婷婷色| 日韩中文字幕av在线| 超碰人人爱人人操| 欧洲尤物不卡播放六区| 久热中文字幕| www.97yy| 色色色色色欧美网| 99青青草| 免费看特别黄色视频| 四季AV一区二区凹凸懂色桃花 | 激情小说在线视频| 青青色综合| 一级少女免费播放电视剧韩剧TV | 日韩精品一区二区三区四在线播放| 小佟丽娅大战91哥| 夜夜狠狠躁日日| 久久免费看视频| 99热中文字幕在线观看| AV在线播放中文字幕| 俺来也最新网址| 黄色一级片在线看| 中国老女人日逼| 久9久9久9久9久9久9| 精品国内视频| 日本AⅤ电影| 久久中文娱乐网| 毛片网站免费| 大香蕉中文网| 91青青草视频| 久热精品在线观看| 日本一区二区三区免费视频| 99国产精品| 性欧美成人18| 一级做a爰片毛片A片| 国产乱伦片、| 中文字幕精品一区久久久久| 中国老女人日逼| 大香蕉偷拍视频| 一级黄色免费视频| 黄色草逼视频| 欧美激情综合网| 五月天婷婷av| 一本色道久久综合熟妇| 午夜精品秘一区二区三区| 91视频在线免费观看| 中文字幕在线观看1| 亚洲精品国产成人无码区在线| 91要爱爱| 亚洲一区视频在线| 黑人亚洲娇小videos∞| 久久免费视频6| 日韩免费中文字幕| 可以免费看的av| 日韩无码网址| 人人射| 亚洲va在线∨a天堂va欧美va| 久久六月天| 91AV在线观看视频| 国产卡一卡二在线| 日韩无码中文字幕视频| 日韩人妻斩| 在线91| 成人精品免费视频| 国产香蕉视频| 欧美成人电影| 国产一二三四| 亚洲无码av中文字幕| 国产av资源网| 日韩一二三四区| 五月天国产精品| 免费A片在线观看| 午夜操日在线| 动漫日逼| 国产成人精品久久二区二区91| 99成人网站| 丝瓜av| 99久视频| 成人视频网站在线观看| 人妻无码蜜桃视频| 精品久久无码中文字幕| www.日韩av| 黄网免费| 韩日精品视频| 欧美日韩成人在线| 怍爱视频| 狼人综合视频| 91网站在线播放| 九九99热| 神马久久午夜| 超碰免费在线| 69av视频在线观看| 国产成人精品无码片子的价格| 久久久成人免费视频| 国产精品二区高清在线苍井空 | 99久视频| 六月婷| 精品九九九九九九| 中文字幕+乱码+中文乱码视频在线观看| 一级午夜| 91中文字幕+乱码| 一区二区三区不卡视频| 欧美日韩在线观看一区| 波多野结衣AV网站| 91无码人妻一区二区成人aⅴ| 久久免费视频播放| 日韩高清无码中文字幕| 美少妇AV| 人人操日本| 中文字幕精品视频在线观看| 国产精品电影| www.cao| 久久婷婷精品| www.日韩av| 无码人妻精品一区二区三区蜜臀百度 | 色播欧美| 国产色视频一区二区三区QQ号| 国产黄色视频在线免费观看| 另类天堂| 少妇三级| 麻豆视频一区二区三区| 91女人18片女毛片60分钟| 精品二区| 色射影院| 3p视频网站| 亚洲中文免费视频| 国产强伦轩免费视频在线| 少妇白浆| 久久黄色视屏| 日韩熟女视频| 五月天成人社区| av少妇| 免费尻屄视频| 成人肏屄视频| 超碰人人干| 国产三级成人| 国产剧情一区二区三区| 亚洲成人精品在线| 午夜黄色视频| 久草视频资源| 北京熟妇搡BBBB搡BBBB| 欧美亚洲成人在线| 肥臀AV在线| 污视频网站免费观看| 国产在线免费视频| 国产在线第一页| 久久无码影视| 中文字幕成人网站| 俺去听听婷婷| 久久久久久久久久久久久自慰小片| 色国产视频| 日日骚av一区二区三区| 日韩久久网| 亚洲精品成人片在线观看精品字幕| 九七在线视频| 岛国免费AV| 日韩中文视频| 熟妇偷拍| 亚洲毛片在线| 三级片大香蕉| 日韩成人无码影片| 欧美久久久久久| 水蜜桃网址| 在线免费三级| 一区二区三区精品无码| 在线激情| 成人女人18女人毛片| 青青操b| 欧美八区| 色婷婷一区二区三区四区五区精品视 | 久久天堂一区| 亚洲欧美日韩激情| 成人三级在线| 日皮视频在线观看免费| 日韩在线视频中文字幕| 特级黄色毛片| 欧美性猛交| 成人无码免费一区二区中文| 婷婷精品| 伊人黄色网| 高清亚洲| 人人妻人人草| 日本欧美成人片AAAA| 成人片免费| 欧美性爱一区二区| 亚洲日韩在线a成| 精品欧美乱码久久久久久| 操逼视频大全| 亚洲国产中文字幕在线播放| 三级片网站视频| 99视频在线| 狠狠ri| www欧美日韩| 亚洲高清无码久久| 97亚洲视频| 久久久国产91桃色一区二区三区 | 一区二区三区无码在线观看| 日本少妇bbw| 青青草精品在线视频| 日批视频网站| 51成人精品午夜福利| 国产精品久久久精品cos| 欧美一级黄色片| 日本AⅤ| 伊人久久免费视频| A级片黄色片| 亚洲秘av无码一区二区| 无码免费看| 蜜桃精品一区二区| 中文字幕国产av| se99av| www污| 欧美性爱中文字幕| 中文字幕国产综合| 国产灬性灬淫灬欲水灬| 亚洲精品国产成人无码区在线| 日本电影一区二区| 嫩草av| 亚洲无码高清免费| 92丨九色丨偷拍老熟女| 一本久久A精品一合区久久久| 校园春色亚洲无码| 无码-ThePorn| 免费黄色av网址| 日韩免费在线观看视频| 国产美女网站| 波多野结衣一区二区三区在线观看| 免费一区二区三区四区| 四虎成人在线| 在线观看黄网| 日日爱网| 亚洲熟女视频| 午夜福利电影无码| 午夜福利大香蕉| 婷婷色综合视频二区| 久久大鸡| 久艹在线| 人人草人人舔| 99久久婷婷国产综合精品hsex,亚 91小宝寻花一区二区三区三级 | 真人一级毛毛片| 国产黃色AAA片| 亚洲网站免费在线观看| 国产足交| 亚欧洲精品视频| 亚洲黄色视频免费看| 欧美一二三区黄色免费视屏| 艹逼网| 麻豆成人91精品二区三区| 日韩中文AV| 日韩色| 欧美日韩性色无码免费| 精品一区二区视频| 日日射视频| 真实国产乱子伦毛片| 日日碰狠狠躁久久躁婷婷| 亚洲欧美日韩一区| 91人妻一区| 国产精品久久久精品cos| 日本成人午夜福利| 国产精品二| 亚洲精品无码久久久| 美日毛片| 精品网站| 国产在线拍揄自揄拍无码网站新闻| 亚洲天堂在线观看视频网站| 大香蕉黄色网| 久久思热国产| 久久久久久久亚洲| 亚洲天堂2016| 另类罕见稀奇videos| 久久成人影音先锋| 欧美性爱免费网站| 国内无码视频| 影音先锋亚洲资源| 激情白浆| 日本无码嫩草一区二区| 国产精品久久久久久无人区| 大香蕉综合在线| 日韩无码av电影| 韩国AV在线| 午夜激情久久| 国产久久视频| 色欲久久久| 999reav| av在线免费观看网址| 尹人香蕉久久| 狠狠干五月天| 人妻少妇中文字幕久久牛牛| 一级全黄120分钟免费| 久久午夜成人电影| 欧美色图另类| 自慰喷水在线观看| 久久精品视频在线| 一级黄色视频片| 免费黄色| 台湾毛片| 欧美精品一区二区少妇免费A片| 最近中文字幕在线| 成人精品永久免费视频99久久精品 | 91欧美精品成人综合在线观看 | AV福利在线观看| 翔田千里无码精品| 天天操夜操| 国产一二三区在线| 黄色一级片视频| 欧美色视| 免费看一区二区三区A片| 日日搔AV一区二区三区| 天天干天天干天天干| 免费成人黄色| 佐山爱人妻无码蜜桃| 18禁网站禁片免费观看| 中文字幕无码综合| 成人AAA| 九九热这里有精品| 亚洲色图15p| 好男人WWW一区二区三区| 爱视频福利网| 丁香成人五月天| 日韩黄色精品| 操逼视频在线| 丁香五月激情啪啪啪| 日韩三级片AV| 久久久久久久久国产| 欧美最猛黑A片黑人猛交蜜桃视频| 91视频一区二区三区| 2025无码视频| 日本特级黄色毛片| 中文字幕五月久久| 日韩午夜无码| www.麻豆网91成人久久久| 色五月婷婷久久| 欧美精品成人免费片| 你懂的网址在线观看| 尹人大香蕉网| 91九色蝌蚪| 一级a免一级a做免费线看内裤的注意事项 | 99草自拍| 欧洲成人免费视频| 蜜桃人妻无码AV天堂二区| 超碰精品| 日韩爱爱免费视频| 成人毛片在线大全免费| 欧美后门菊门交| 无码人妻少妇| 亚欧成人在线视频| 欧一美一婬一伦一区二区三区黑人| 亚洲AV无码乱码国产| 91香蕉| 国产AV大片| 7777精品伊人久久7777| 国产成人视频在线观看| 国产精品高潮呻吟久久| 岛国av无码免费| 午夜福利毛片| 中文字幕精品一区| 久热9191| 狠狠干狠狠撸| 中文字幕人妻在线中文乱码怎么解决| 啪视频网站国产馆| 九九热热| 丁香五月中文| 黄色一级爱爱| 无码一二三区| 国产内射网站| 日韩主播在线| 水蜜桃一区| 丰满人妻一区二区三区视频54| 2025天天操夜夜操| 婷婷五月激情网| 亚洲乱码中文字幕| 婷婷在线观看免费| 日本操B| 成人四区| 久久伊人亚洲| 在线免费观看黄色视频| 色综合久久天天综合网| 99操99| 秋霞91| 躁BBB躁BBB添BBBBBB| 无码做爱视频| 久久国产精| 人人看人人摸人人| 国产精品乱子伦一区二区三区视频 | 超碰人人操人人爱| 91精品国产一区二区| AV1区二区| 无码在线免费观看视频| 91超碰久久在线| 黄色av网| 亚洲一区| 黄色美女网站| 亚洲先锋影音| 精品国产AV鲁一鲁一区| 精品福利在线| 亚洲电影无码| 国产精品小电影| 国产一区二区00000视频| 国产色情在线| 亚洲九九视频| 亚洲国产高清国产精品| 日韩无码不卡| 99精品丰满人妻无码| 18啪啪网站| 中文字幕日韩无码片| 久久国内视频| 日韩性做爰免费A片AA片| 69福利社| 欧美综合亚洲图片综合区| 三级成人无码| 国产一区二区电影| 精品久久久无码| 无码免费视频| 狠狠干大香蕉| 亚洲综合中文字幕在线| 97人操| 色aV牛牛在线观看| 亚洲视频免费播放| 亚洲精品成人无码AV在线| 五月丁香中文| 韩国午夜激情| 性无码一区二区三区| 裸体美女视频欧美18| 午夜视频成人| 人人干人人操人人爽| 欧美色图在线播放| 熟睡侵犯の奶水授乳在线| 中韩日美免费看的电影| 麻豆视频在线免费观看| 五月久久婷婷| 加勒比精品在线| 91久久电影| 2022天天干| 天天插在线视频| 国产女人18毛片18精品| 国产嫩草精品A88AV| 亚洲综合视频网| 激情黄色毛片| 高清无码免费视频| 成人影音先锋| 美腿丝袜中文字幕精品| av在线三级| 影音先锋女人资源| 日批视频| 亚洲黄色免费网站| 老湿机福利视频| 天天撸在线| 日本免费在线观看视频| 亚洲综合一二三区| 中文字幕视频在线| 91成人电影在线| 一区二区三区网站| 九九99精品视频| 免费av一区二区| 91成人免费视频| 亚洲AV无码成人精品区欧洲| 俺来也在线视频| 天堂在线中文网| 国产精品久久77777| 美女三片| 天堂网在线视频| 视频一区二区三区免费| 特级欧美AAAAAA| 一级a一级a免费观看免免黄‘/| 人人妻日日摸狠狠躁| 青青草原av| 国产人妖在线观看| 亚洲色小说| 坏男人内射老太太| 欧美MV日韩MV国产网站| 苍井空中文字幕在线观看| 亚州无码| www.91爱爱,com| 一卡二卡无码| 香蕉AV777XXX色综合一区| 日无码视频| 欧美一区二区三区在线播放| A级片黄色片| 蜜臀久久99精品久久久巴士| 日本午夜福利电影| 日本成人三级片| 日韩AV无码专区亚洲AV| 2025无码视频| 亚洲精品aaa| 91九色麻豆| 日本高清一区二区高清免费视频| 大香蕉手机视频| 欧美a在线观看| 九九精品在线观看| 人人干天天干| 国产成人AV一区二区三区在线观看| 成人动漫免费观看| 日韩一级无码毛片| 韩国GOGOGO高清| 蜜臀久久99精品久久久晴天影视| 自拍偷拍中文字幕| 老女人日逼视频| 插插插菊花综合网| 五月天丁香花| 日韩成人无码精品| 人妻懂色av粉嫩av浪潮av| 国产免费一区二区三区免费视频| 蜜桃av| 丁香久久| 欧美午夜福利在线观看| 色综合久久天天综合网| 免费日韩视频| 色欲影音| 三级黄色免费网站| 男女成人视频| 欧美日韩中文视频| 先锋影音亚洲AV每日资源网站 | AV色站| 国产丝袜无码| 俺也去网站| 亚洲天堂网在线观看视频| 特级西西WWW无码| 日本親子亂子倫XXXX| 欧美A片免费观看| aaa在线免费视频| 操逼视频在线观看| 高清无码在线看| 青娱乐成人| 国产欧美精品一区二区| 91视频久久久| 91丨九色丨熟女丰满| 女生操逼网站| 成人欧美精品| 日本亚洲中文字幕| 天天日天天| 在线观看中文字幕一区| 性猛交AAAA片免费观看直播 | 污污污www精品国产网站| 精品乱子伦一区二区三区免费播成 | 精品无码一区二区三区四区| 亚洲无码视频免费看| 色资源在线| 黄色小网站在线观看| 日本综合久久| 国产精品色视频| 欧美色国| 香蕉AV777XXX色综合一区| 大香蕉东京热| 国产高清久久| 天天日天天操天天摸天天干天日射天天插| 国产成人综合在线| 欧美成人网站免费在线观看| 在线观看无码高清视频| 91人人妻人人澡人人爽人人精品 | 国产成人精品AV在线观| 热无码| 精品无码一区二区三| 91拍真实国产伦偷精品| 影音先锋成人资源站| 欧美猛交| а√最新版天堂中文在线| 尤物网在线| 亚洲AV成人精品日韩在线播放| 无码一区二| 啪啪毛片| 亚洲你懂的| 免费无码婬片AAAA片直播| 黄色视频网站在线免费观看| 91人妻人人澡人人爽人人精| 久久在线精品| 神马午夜| 亚洲激情视频在线观看| 婷婷五月天网| 丁香五月婷婷在线| 欧美久久精品| 激情黄色视频| www.精品视频| 亚洲无码一级片| 久久国产综合| 国产剧情在线| 超碰啪啪| 免费一级做a爱片毛片A片小说| 狠狠干大香蕉| 成年人黄色片| 欧美日韩国产成人| 亚洲AV在线免费观看| 成人日韩无码| 足浴小少妇-88AX| 成人黄色免费| 国产欧美一区二区精品性色超碰| 三级视频网站| AV在线资源| 无码东京热国产| 欧美成人片免费看| 国产av一二三区| 边吃奶边做爱| 综合久久av| 1024香蕉视频| 国产福利在线导航| 黄色片视频日韩| 日本一级特级毛片视频| AV大片在线观看| 夫妻-ThePorn| 午夜成人中文字幕| 41ts午夜福利| 豆花视频成人版www满18| 91在线免费视频观看| 爱爱无码视频| 五月婷婷一区| 99在线观看免费视频| 免费a级毛片| 亚洲一区二区三区无码| 免费无码视频| 青草大香蕉| 国产乱婬AV片免费| 久久性爱免费视频| 玖玖资源在线观看| 99操99| 国产无遮挡又黄又爽又色视频| 国产精品国产三级国产专区53| 五月丁香婷婷激情| 欧美丰满美乳XXⅩ高潮www| 欧美一級黃色A片免費看| 免费无码成人片在线播放| 成人一级视频| 黄色在线观看免费| 日韩中文字幕无码| 亚洲AV无码乱码AV| 高清毛片AAAAAAAAA片| 91麻豆国产视频| a片在线免费播放| 97超碰资源站| 嫩BX区二区三区的区别| 亚洲无码高清一区| 影音先锋国产| 免费av大全| 亚洲成人无码在线观看| 三级片青青草| 综合久久av| 国产精品人人人人| 在线亚洲AV| 操逼逼综合网| 亚洲乱码精品久久久久..| 视色av| 伊人久久婷婷| 久久久婷婷| 久热9191| 亚洲精品日韩综合观看成人91| 另类国产| 亚洲男人的天堂视频网在线观看+720P | 成人黄色大香蕉| 大香蕉久久久久久久| 操逼999| 欧美极品另类| 亚洲秘一区二区三区-精品亚洲二区- | 麻豆视频一区二区三区| 国产精品久久久久无码| 内射91| 色诱av| 国产午夜视频| 日本高清视频网站| 国产精品无| 狼人色综合| 天天摸天天看| A级片在线观看| 四川w搡BBB搡wBBB搡| 亚洲免费清高| 亚洲vs无码蜜桃少妇| 国产一区二区波多野结衣| 中文字幕日本人妻| 欧美性性生交XXXXX无码| 亚洲欧美日韩一区二区| 国产黄色自拍视频| 久久中文字幕电影| 精品国产免费无码久久噜噜噜AV| 北条麻妃99精品青青久久| 日本乱伦网| 天天骑夜夜操| 久久久久久久国产精品| 久久视频理论| 狠狠色噜噜狠狠狠7777米奇网| 久操久干| 自拍偷拍精品视频| 夜夜嗨av| 精品免费国产一区二区三区四区的使用方法 | 91丨人妻丨国产丨丝袜| 激情五月天小说网| 天天天做夜夜夜爽无码| 大香蕉伊人综合网| 青青操网站| 国产福利网| 懂色在线精品分类视频| 一级aa视频| 污网站18禁| 在线免费看A片| AV天堂亚洲| 北条麻妃一区二区三区-免费免费高清观看 | 亚洲vs天堂vs成人vs无码| 9久精品| 黄总AV| 亚洲精品无码中文字幕| 免费av大全| 日韩天堂av| 少妇BBBB| 97色色婷婷| 蜜桃视频成人app| 黄片网站免费| 日操操| 国产精品久久久久久99| 无码在线观看免费视频| 大色网小色网| 精品人妻一区二区三区在| 亚洲天堂AV2025| 91视频网站免费| 一区二区三区色| 欧美日韩精品在线| 成人国产精品免费观看| 丁香五月在线播放| 熟女少妇一区二区三区| 一区二区三区无码在线观看| 午夜黄片| 六月丁香综合| 在线观看视频亚洲| 西西444WWW无码大胆| 国产小视频在线观看| 亚洲色综合网| 国产精品一区二区在线观看| wwwxxx18| 蜜桃av| 大BBBw大BBBW另类| 亚洲尤物在线| 人妻一区| 亚洲性爱网站| 少妇搡BBBB搡BBB搡造水多,| 成人AV一区二区三区| 97成人人妻一区二区三区| 国产操逼网站| 91视频首页| 伦理被部长侵犯HD中字| 欧美性猛交XXXX乱大交3| 嫩草av在线| 欧美性性性| 五月婷婷无码| 日本18禁网站| 免费看黄片| 日本乱伦网站| 成人A片免费看| 北条麻妃一区二区三区-免费免费高清观看 | 又大又长又粗91| 天天撸在线| 尤物免费视频| 五夜福利成人视频| 成人黄色AV网站| 日本操逼片| a视频在线| 欧美啪啪视频| 国产区在线| 黄色视频亚洲| 97男人的天堂| 另类国产| 人妻无码久久| 亚洲高清无码在线观看| 91在线电影| 国产成人无码AⅤ片免费播放| 日韩无码中文字幕| JIZZJIZZ国产精品喷水| 吹潮喷水高潮HD| 人人操在线观看| 成人电影aaa| 日本一级特级毛片视频| 岛国无码破解AV在线播放| 色网在线观看| 国产欧美精品一区二区三区| 北条麻妃性爱视频| 97在线超碰| 三级黄色小视频| 日韩啪啪啪网站| 婷婷五月天综合网| 影音先锋成人视频| 欧美日韩一区二区三区四区| 亚洲aa| 欧美激情无码炮击| 日韩久久婷婷| 色婷婷Av| 大香蕉福利视频导航| 99色婷婷| 五月天国产精品| 北条麻妃无码一区三区| 夸克看成人片一级A片| 韩国无码一区二区三区| 麻豆91网站| 少妇探花| 岛国无码在线观看| 性猛交╳XXX乱大交| 成人精品123| 丁香五月婷婷色| 精品孕妇一级A片免费看| 天天日天天操天天摸天天干天日射天天插 | 探花av| 亚洲中文字幕无码在线观看| 亚洲美女操| 欧美性爱在线观看| 无码国产99精品久久久久网站 | 91乱子伦国产乱子伦无码| 高清无码视频免费看| 亚洲v欧美| 韩国午夜激情| www.豆花福利视频| 成人视频一区二区| 99久久久国产精品免费蜜臀| 日本精品黄色视频| 日韩视频一区二区| 爱搞搞就要爱搞搞| 久久XX| 一见钟情的韩国电影| 成人在线第一页| 国产区av| 中文字幕69| 久久婷婷激情| 天天色天天| 久久久久黄片| 精品无码免费| 影音先锋AV成人| 一区二区三区四区免费看| 亚洲小说区图片区| 大香蕉伊人视频在线观看| 夜夜嗨AV一区二区三区| 日韩AV无码网站| 一级a免一级a做免费线看内祥|