基于本人觀看學(xué)習(xí) 哈工大李治軍老師主講的操作系統(tǒng)課程 所做的筆記,僅進(jìn)行交流分享
特此鳴謝李治軍老師,操作系統(tǒng)的神作!
如果本篇筆記幫助到了你,還請(qǐng)點(diǎn)贊 關(guān)注 支持一下 ?>??<)!!
主頁(yè)專欄有更多,如有疑問(wèn)歡迎大家指正討論,共同進(jìn)步!
給大家跳段街舞感謝支持!? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
第二章 進(jìn)程與線程 (上)
更多操作系統(tǒng)筆記:【哈工大李治軍老師】操作系統(tǒng)筆記專欄匯總
如果有需要markdown或者PDF可以私信我,可以在此基礎(chǔ)上自己添加補(bǔ)充筆記(●’?’●)
課程鏈接:
b站: 【哈工大】操作系統(tǒng) 李治軍(全32講)
大學(xué)MOOC:大學(xué)慕課—操作系統(tǒng)—主講:哈工大李治軍
一、CPU管理的直觀想法
操作系統(tǒng)在管理CPU時(shí)引入了一個(gè)多進(jìn)程圖像,通過(guò)多進(jìn)程圖像操作系統(tǒng)管理CPU
多進(jìn)程圖像是操作系統(tǒng)的核心圖像。
1.CPU的工作原理
- 取指:CPU 從內(nèi)存中讀取指令,并解析指令中的操作碼和操作數(shù)等信息。
- 執(zhí)行:根據(jù)指令中的操作碼和操作數(shù),CPU 進(jìn)行相應(yīng)的邏輯或算術(shù)運(yùn)算,并將結(jié)果保存到寄存器或內(nèi)存中。
- 寫回:如果結(jié)果需要保存到內(nèi)存中,則將結(jié)果寫入內(nèi)存,或者將結(jié)果保存到寄存器中供后續(xù)指令使用。
- 重復(fù):不斷重復(fù)上述步驟,直到程序執(zhí)行結(jié)束。
-
取指:CPU 從內(nèi)存中讀取指令,并解析指令中包含的操作碼和操作數(shù)等信息。
-
執(zhí)行:根據(jù)指令中的操作碼和操作數(shù),CPU 進(jìn)行相應(yīng)的邏輯或算術(shù)運(yùn)算,并將結(jié)果保存到寄存器或內(nèi)存中。
-
寫回:如果結(jié)果需要保存到內(nèi)存中,則將結(jié)果寫入內(nèi)存;否則,將結(jié)果保存到寄存器中供后續(xù)指令使用。
-
重復(fù):不斷重復(fù)上述步驟,直到程序執(zhí)行結(jié)束。
設(shè)置PC初始值,操作系統(tǒng)會(huì)自動(dòng)取指執(zhí)行
有IO指令和沒(méi)有IO指令執(zhí)行時(shí)間之比:
可以看出IO執(zhí)行特別慢,CPU利用率非常低
如何解決這個(gè)問(wèn)題?
在等待IO過(guò)程中,CPU切出去執(zhí)行其他程序,讓CPU充分忙碌起來(lái),提高了利用率
2.多道程序,交替執(zhí)行
舉例單道程序和多道程序CPU利用率對(duì)比:
這種多道程序同時(shí)出發(fā),交替執(zhí)行就是并發(fā)。
CPU應(yīng)該工作的樣子:
3.如何做到并發(fā)?
對(duì)于切換程序執(zhí)行,因?yàn)閍x,bx改變了,只修改寄存器PC不能找到原來(lái)程序執(zhí)行到哪里。
在切出程序后,原來(lái)的程序執(zhí)行到哪里,執(zhí)行的樣子 需要記錄下來(lái),切回時(shí)才能繼續(xù)執(zhí)行
由此看出 運(yùn)行的程序和靜態(tài)程序不一樣:運(yùn)行的程序需要記錄運(yùn)行后的時(shí)刻
4.進(jìn)程
進(jìn)程:刻畫運(yùn)行中的程序 一個(gè)運(yùn)行中的程序就是一個(gè)進(jìn)程
進(jìn)程有開(kāi)始、有結(jié)束,程序沒(méi)有
進(jìn)程會(huì)走走停停,走停對(duì)程序無(wú)意義
進(jìn)程需要記錄ax,bx,…,程序不用
記錄這些信息的數(shù)據(jù)結(jié)構(gòu)就是:PCB
多個(gè)程序同時(shí)運(yùn)行就是多進(jìn)程,CPU進(jìn)行管理。
PCB中記錄了操作系統(tǒng)所需的,用于描述進(jìn)程的當(dāng)前情況以及控制進(jìn)程運(yùn)行的全部信息。
操作系統(tǒng)根據(jù)PCB來(lái)對(duì)并發(fā)執(zhí)行的進(jìn)程進(jìn)行控制和管理。
二、多進(jìn)程圖像
1.多進(jìn)程圖像是操作系統(tǒng)的核心圖像
從上層用戶的角度看:共有三個(gè)進(jìn)程PID:1 PID:2 PID:3
操作系統(tǒng)根據(jù)PCB合理推進(jìn)執(zhí)行多個(gè)進(jìn)程
啟動(dòng)了的程序就是進(jìn)程,所以是多個(gè)進(jìn)程推進(jìn)操作系統(tǒng)只需要把這些進(jìn)程記錄好、要按照合理的次序推進(jìn)(分配資源、進(jìn)行調(diào)度)這就是多進(jìn)程圖像。
我們每要解決一個(gè)任務(wù),計(jì)算機(jī)都會(huì)創(chuàng)建一個(gè)進(jìn)程來(lái)執(zhí)行這個(gè)任務(wù)。 多進(jìn)程圖像是操作系統(tǒng)的核心圖像
windows任務(wù)管理器中可以查看多個(gè)進(jìn)程同時(shí)執(zhí)行,操作系統(tǒng)通過(guò)管理進(jìn)程實(shí)現(xiàn)對(duì)計(jì)算機(jī)的管理
2.多進(jìn)程如何組織?
通過(guò)PCB形成一系列數(shù)據(jù)結(jié)構(gòu),操作系統(tǒng)推進(jìn)進(jìn)程的執(zhí)行
3.進(jìn)程狀態(tài)圖:
多進(jìn)程的組織:PCB+狀態(tài)+隊(duì)列
運(yùn)行->等待; 運(yùn)行->就緒; 就緒->運(yùn)行…
進(jìn)程狀態(tài)圖能給出進(jìn)程生存期的清晰描述,是認(rèn)識(shí)操作系統(tǒng)進(jìn)程管理的一個(gè)窗口。
掛起:掛起是指操作系統(tǒng)將某個(gè)正在運(yùn)行的進(jìn)程暫時(shí)停止執(zhí)行,并將其狀態(tài)保存到外部存儲(chǔ)器或內(nèi)存中,直到以后再次恢復(fù)該進(jìn)程執(zhí)行。是一種重要的管理和優(yōu)化技術(shù),它可以減少系統(tǒng)資源的浪費(fèi),提高系統(tǒng)的響應(yīng)速度和可用性。
在進(jìn)程掛起期間,進(jìn)程的狀態(tài)信息被保存到外部存儲(chǔ)器或內(nèi)存中,當(dāng)操作系統(tǒng)需要重新啟動(dòng)該進(jìn)程時(shí),可以從保存的狀態(tài)信息中還原該進(jìn)程的上下文,繼續(xù)執(zhí)行。
主動(dòng)掛起:是指進(jìn)程自己向操作系統(tǒng)申請(qǐng)掛起自己的狀態(tài),通常是因?yàn)楫?dāng)前執(zhí)行的任務(wù)已經(jīng)完成,但該進(jìn)程還需要保留下來(lái),以便稍后根據(jù)需要進(jìn)行繼續(xù)執(zhí)行。例如暫停操作、文件下載中暫停/繼續(xù)操作等
被動(dòng)掛起:是指操作系統(tǒng)強(qiáng)制掛起某個(gè)正在執(zhí)行的進(jìn)程,因?yàn)橄到y(tǒng)資源已經(jīng)不足,或者該進(jìn)程所請(qǐng)求的資源無(wú)法獲得,此時(shí)操作系統(tǒng)會(huì)暫時(shí)停止該進(jìn)程執(zhí)行,以便其他進(jìn)程可以更好地利用系統(tǒng)資源。
4.多進(jìn)程如何交替?
5.多進(jìn)程如何影響?
多個(gè)進(jìn)程同時(shí)在存在于內(nèi)存會(huì)出現(xiàn)下面的問(wèn)題
進(jìn)程1中地址100訪問(wèn)到了同時(shí)運(yùn)行的進(jìn)程2中的地址100:
解決的辦法:
限制對(duì)地址100的讀寫
多進(jìn)程的地址空間分離: 內(nèi)存管理的主要內(nèi)容
為什么說(shuō)進(jìn)程管理連帶內(nèi)存管理形成多進(jìn)程圖像?
6.多進(jìn)程如何合作?
隊(duì)列中的進(jìn)程放入和取出 多個(gè)進(jìn)程交替執(zhí)行
生產(chǎn)者—消費(fèi)者實(shí)例
共享緩沖區(qū):
兩個(gè)合作的進(jìn)程都要修改counter:
counter語(yǔ)義錯(cuò)誤:初始counter=5,進(jìn)行加一減一應(yīng)該還是五,但經(jīng)過(guò)執(zhí)行序列得到的counter為4,進(jìn)程必須合理推進(jìn)
核心在于進(jìn)程同步:
讀寫PCB,OS中最重要的結(jié)構(gòu),貫穿始終
三、用戶級(jí)線程
1.資源切換(引出線程概念)
如何將資源不動(dòng)而切換指令序列?
線程切換分為指令切換 和 資源切換 分治
進(jìn)程 = 資源 + 指令執(zhí)行序列
將資源和指令執(zhí)行分開(kāi)一個(gè)資源 + 多個(gè)指令執(zhí)行序列
既有多個(gè)指令在同時(shí)觸發(fā)交替執(zhí)行,切換也不用那么復(fù)雜:
線程: 保留了并發(fā)的優(yōu)點(diǎn),避免了進(jìn)程切換代價(jià)
實(shí)質(zhì)就是內(nèi)存映射表不變而PC指針改變
多個(gè)執(zhí)行序列+一個(gè)地址空間是否實(shí)用?
一個(gè)網(wǎng)頁(yè)瀏覽器: 同時(shí)觸發(fā),交替執(zhí)行:
一個(gè)線程用來(lái)從服務(wù)器接收數(shù)據(jù)
一個(gè)線程用來(lái)顯示文本
一個(gè)線程用來(lái)處理圖片(如解壓縮)
一個(gè)線程用來(lái)顯示圖片
下載一段網(wǎng)頁(yè)——顯示文本——再回來(lái)下載圖片…
這些線程要共享資源嗎?
接收數(shù)據(jù)放在100處,顯示時(shí)要讀… 寫入讀出緩沖區(qū)
所有的文本、圖片都顯示在一個(gè)屏幕上
多線程表達(dá)的切換指令序列對(duì)進(jìn)程切換很有價(jià)值。
2.線程切換
啟動(dòng)多個(gè)線程,每個(gè)線程執(zhí)行函數(shù)
核心是Yield…
能切換了就知道切換時(shí)需要是個(gè)什么樣子
Create就是要制造出第一次切換時(shí)應(yīng)該的樣子
如果繼續(xù)往下執(zhí)行跳轉(zhuǎn)到另一個(gè)線程,因?yàn)閮蓚€(gè)線程共用了一個(gè)棧
每個(gè)指令序列中,函數(shù)調(diào)用應(yīng)該用自己的棧?。?!
從一個(gè)棧到兩個(gè)棧
TCB任務(wù)控制塊,包含了線程的信息,如寄存器狀態(tài)、堆棧指針、優(yōu)先級(jí)、資源占用等
TCB 在任務(wù)/線程切換時(shí)用于保存當(dāng)前任務(wù)/線程的狀態(tài)信息,以便后續(xù)再次恢復(fù)執(zhí)行
(jmp 204;應(yīng)該去掉)
ThreadCreate的核心就是用程序做出三樣?xùn)|西:
多個(gè)程序出現(xiàn)在內(nèi)存中執(zhí)行,在程序執(zhí)行的過(guò)程中調(diào)用Yield(),首先切換棧然后再?gòu)棗?,?shí)現(xiàn)切換到另外一個(gè)線程執(zhí)行,在Yield()…
3.用戶級(jí)線程與核心級(jí)線程
如果進(jìn)程的某個(gè)線程進(jìn)入內(nèi)核并阻塞
一旦一個(gè)線程阻塞,其他線程也將被阻塞,會(huì)切換到另一個(gè)進(jìn)程執(zhí)行
雖然通過(guò)用戶級(jí)線程啟動(dòng)多個(gè)序列,但是CPU發(fā)生阻塞等待
核心級(jí)線程ThreadCreate是系統(tǒng)調(diào)用,會(huì)進(jìn)入內(nèi)核
TCB在內(nèi)核中,內(nèi)核中一個(gè)線程阻塞,將會(huì)切換到另一個(gè)線程執(zhí)行
因此內(nèi)核級(jí)線程的并發(fā)性更好
核心級(jí)線程完全由操作系統(tǒng)在內(nèi)核中決定,比用戶級(jí)線程復(fù)雜
四、內(nèi)核級(jí)線程
和用戶級(jí)相比,核心級(jí)線程有什么不同?
ThreadCreate是系統(tǒng)調(diào)用,內(nèi)核管理TCB,內(nèi)核負(fù)責(zé)切換線程
如何讓切換成型? ——內(nèi)核棧,TCB
用戶棧是否還要用?執(zhí)行的代碼仍然在用戶態(tài),還要進(jìn)行函數(shù)調(diào)用
一個(gè)棧到一套棧:兩個(gè)棧到兩套棧
1.用戶棧和內(nèi)核棧之間的關(guān)聯(lián)
用戶棧和內(nèi)核棧是操作系統(tǒng)中兩個(gè)重要的棧空間,它們分別用于存儲(chǔ)用戶態(tài)和內(nèi)核態(tài)的執(zhí)行環(huán)境
當(dāng)一個(gè)進(jìn)程從用戶態(tài)切換到內(nèi)核態(tài)時(shí),需要使用到內(nèi)核棧。進(jìn)程從內(nèi)核態(tài)返回用戶態(tài)時(shí),需要使用到用戶棧
·所有中斷(時(shí)鐘、外設(shè)、INT指令)都引起上述切換
·中斷(硬件)又一次幫助了操作系統(tǒng)…
用戶棧和內(nèi)核棧是操作系統(tǒng)中兩個(gè)不同的棧區(qū)域,它們各自負(fù)責(zé)存儲(chǔ)不同執(zhí)行環(huán)境的棧幀信息
在處理器發(fā)生中斷時(shí),或者進(jìn)程主動(dòng)發(fā)起系統(tǒng)調(diào)用時(shí),CPU會(huì)切換到內(nèi)核態(tài),并將當(dāng)前進(jìn)程的用戶態(tài)上下文信息保存到它的用戶棧中,然后切換到內(nèi)核棧中繼續(xù)執(zhí)行相應(yīng)的內(nèi)核代碼;當(dāng)內(nèi)核完成相應(yīng)的處理邏輯后,再將內(nèi)核棧中保存的內(nèi)容彈出,恢復(fù)用戶棧中保存的用戶態(tài)上下文信息,最后切換回用戶態(tài)繼續(xù)執(zhí)行用戶進(jìn)程。
2.開(kāi)始內(nèi)核中的切換:switch_to
switch to:仍然是通過(guò)TCB找到內(nèi)核棧指針;然后通過(guò)ret切到某個(gè)內(nèi)核程序;最后再用CS:PC切到用戶程序
switch to也稱為上下文切換,當(dāng)多個(gè)任務(wù)或線程同時(shí)運(yùn)行時(shí),操作系統(tǒng)需要在它們之間進(jìn)行快速的切換,實(shí)現(xiàn)并發(fā)執(zhí)行
“五段論”保證了線程之間的正確切換和執(zhí)行:
用戶級(jí)線程、核心級(jí)線程的對(duì)比:
用戶級(jí)線程是由應(yīng)用程序開(kāi)發(fā)者創(chuàng)建和管理的線程,運(yùn)行在用戶空間,并通過(guò)用戶程序調(diào)用系統(tǒng)調(diào)度庫(kù)來(lái)實(shí)現(xiàn)線程的調(diào)度和同步
每個(gè)用戶級(jí)線程都對(duì)應(yīng)著一個(gè)內(nèi)核級(jí)線程,內(nèi)核級(jí)線程以操作系統(tǒng)內(nèi)核的身份運(yùn)行并提供線程與系統(tǒng)資源之間的映射
用戶級(jí)線程實(shí)現(xiàn)簡(jiǎn)單,調(diào)度和同步開(kāi)銷小,缺點(diǎn)是不能利用多處理器環(huán)境提高性能
核心級(jí)線程是由操作系統(tǒng)內(nèi)核創(chuàng)建和管理的線程,直接由內(nèi)核調(diào)度器進(jìn)行調(diào)度
與用戶級(jí)線程相比,內(nèi)核級(jí)線程有更好的并發(fā)性和CPU利用率,但比較復(fù)雜。
五、內(nèi)核級(jí)線程實(shí)現(xiàn)
內(nèi)核級(jí)線程需要采用復(fù)雜的數(shù)據(jù)結(jié)構(gòu)來(lái)維護(hù)線程上下文切換和狀態(tài)信息,并且需要在內(nèi)核態(tài)進(jìn)行線程切換
核心是讓操作系統(tǒng)內(nèi)核直接管理線程調(diào)度,對(duì)于上層應(yīng)用程序來(lái)說(shuō),無(wú)需關(guān)心線程的創(chuàng)建、調(diào)度和同步等
先從用戶棧到內(nèi)核棧,再?gòu)膬?nèi)核棧到用戶棧;核心級(jí)線程的兩套棧,核心是內(nèi)核棧。
1.int 0x80 fork( )
fork() 系統(tǒng)調(diào)用可以讓程序生成一個(gè)新的獨(dú)立進(jìn)程,并在原進(jìn)程和新進(jìn)程中進(jìn)行不同的操作
2.切換五段論中的中斷入口和出口
中斷入口: _system_call將用戶態(tài)信息壓棧
任務(wù)的運(yùn)行狀態(tài)如果不在就緒狀態(tài)就執(zhí)行調(diào)度,如果在就緒狀態(tài)但counter等于0,也執(zhí)行調(diào)度程序
中斷出口:
sys_fork 函數(shù)調(diào)用了 fork() 系統(tǒng)調(diào)用,它會(huì)通過(guò) eax 寄存器返回新創(chuàng)建進(jìn)程的進(jìn)程 ID,在此之前會(huì)先將該寄存器的值入棧保存
接著通過(guò) cmp 判斷是否需要進(jìn)行進(jìn)程調(diào)度,并將返回地址入棧后通過(guò) jmp 指令跳轉(zhuǎn)到 schedule 函數(shù)執(zhí)行進(jìn)程切換操作
在進(jìn)程切換結(jié)束后,通過(guò) pop 指令將原 eax 寄存器的值恢復(fù)回來(lái)fork() 調(diào)用的返回值
3.switch to
任務(wù)狀態(tài)段Tss(Task State Segment)表示任務(wù)狀態(tài)段的表項(xiàng),用于獲取相應(yīng)進(jìn)程的任務(wù)結(jié)構(gòu)體的起始地址
跳轉(zhuǎn)到所切換到的進(jìn)程的任務(wù)結(jié)構(gòu)體中保存的代碼起始地址,從而實(shí)現(xiàn)進(jìn)程上下文切換的操作:
Linux 0.11用tss切換,但也可以用棧切換,因?yàn)閠ss中的信息可以寫到內(nèi)核棧中
4.ThreadCreate
fork()使用 push 指令將寄存器 %gs 和 %eax 的值分別壓入棧中
然后并調(diào)用_copy_process 函數(shù)創(chuàng)建新進(jìn)程
·在 _copy_process函數(shù)中,使用給定的參數(shù)構(gòu)造一個(gè)新進(jìn)程的狀態(tài)
這些參數(shù)全部傳入 _copy_process函數(shù)設(shè)置上下文信息
然后函數(shù)返回到 sys_fork 函數(shù)并使用 add 指令來(lái)從棧中刪除參數(shù),最終 ret 返回
copy_process的細(xì)節(jié):創(chuàng)建棧
調(diào)用 get_free_page 函數(shù)來(lái)動(dòng)態(tài)申請(qǐng)一頁(yè)大小的內(nèi)存空間,并轉(zhuǎn)換為一個(gè)指向PCB的指針 p
創(chuàng)建TCB——?jiǎng)?chuàng)建內(nèi)核棧和用戶?!P(guān)聯(lián)棧和TCB 子進(jìn)程和父進(jìn)程共享用戶棧
copy_process的細(xì)節(jié):執(zhí)行前準(zhǔn)備
5.如何執(zhí)行我們想要的代碼?
fork() 調(diào)用成功時(shí),返回值為子進(jìn)程的 PID 在父進(jìn)程中。在子進(jìn)程中,fork() 返回 0。
exec() 是一個(gè)系統(tǒng)調(diào)用,會(huì)執(zhí)行 system_call
ex.a_entry是可執(zhí)行程序入口地址,產(chǎn)生可執(zhí)行文件時(shí)寫入
內(nèi)核級(jí)線程總結(jié)
六、操作系統(tǒng)的“樹(shù)”(知識(shí)串講總結(jié))
前面知識(shí)的串聯(lián)
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-431993.html
更多操作系統(tǒng)筆記:【哈工大李治軍老師】操作系統(tǒng)筆記專欄匯總
第二章 下:操作系統(tǒng)第二章(下)學(xué)習(xí)筆記
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-431993.html
大家的點(diǎn)贊、收藏、關(guān)注將是我更新的最大動(dòng)力!歡迎留言或私信建議或問(wèn)題。 大家的支持和反饋對(duì)我來(lái)說(shuō)意義重大,我會(huì)繼續(xù)不斷努力提供有價(jià)值的內(nèi)容! |
到了這里,關(guān)于【操作系統(tǒng)OS】學(xué)習(xí)筆記:第二章 進(jìn)程與線程 (上)【哈工大李治軍老師】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!