王道操作系統(tǒng)第2章-進(jìn)程管理-進(jìn)程與線程
王道操作系統(tǒng)第2章-進(jìn)程管理-進(jìn)程與線程






進(jìn)程的概念、組成、特征
程序:是靜態(tài)的,就是存放在磁盤里的可執(zhí)行文件,就是一系列的指令集合
進(jìn)程(Process):是動(dòng)態(tài)地,是程序的一次執(zhí)行過(guò)程,同一個(gè)程序多次執(zhí)行會(huì)對(duì)應(yīng)多個(gè)進(jìn)程
進(jìn)程的組成
進(jìn)程由PCB、程序段、數(shù)據(jù)段組成
PCB
當(dāng)進(jìn)程被創(chuàng)建時(shí),操作系統(tǒng)會(huì)為該進(jìn)程分配一個(gè)唯一的、不重復(fù)的“身份證號(hào)”——PID(process ID)
操作系統(tǒng)要記錄PID、進(jìn)程所屬用戶ID(UID)
還要記錄給進(jìn)程分配了哪些資源(如分配了多少內(nèi)存、正在使用哪些IO設(shè)備、正在使用哪些文件),可用于實(shí)現(xiàn)操作系統(tǒng)對(duì)資源的管理
還要記錄進(jìn)程的運(yùn)行情況(如CPU使用時(shí)間、磁盤使用情況、網(wǎng)絡(luò)流量使用情況等),可用于實(shí)現(xiàn)操作系統(tǒng)對(duì)進(jìn)程的控制、調(diào)度
這些信息都被保存在一個(gè)數(shù)據(jù)結(jié)構(gòu)PCB(Process Control Block)中,即進(jìn)程控制塊 操作系統(tǒng)需要對(duì)各個(gè)并發(fā)運(yùn)行的進(jìn)程進(jìn)行管理,但凡管理時(shí)所需要的信息,都會(huì)被放在PCB中
PCB是進(jìn)程存在的唯一標(biāo)志,當(dāng)進(jìn)程被創(chuàng)建時(shí),操作系統(tǒng)為其創(chuàng)建PCB,當(dāng)進(jìn)程結(jié)束時(shí),會(huì)回收其PCB
程序段、數(shù)據(jù)段
PCB是給操作系統(tǒng)用的,程序段、數(shù)據(jù)段是給進(jìn)程自己用的
進(jìn)程的特征
程序是靜態(tài)的,進(jìn)程是動(dòng)態(tài)的,相比與程序,進(jìn)程有如下特征
動(dòng)態(tài)性:動(dòng)態(tài)性是進(jìn)程最基本的特征,進(jìn)程是程序的一次執(zhí)行過(guò)程,是動(dòng)態(tài)地產(chǎn)生、變化和消亡的
并發(fā)性:內(nèi)存中有多個(gè)進(jìn)程實(shí)體,各進(jìn)程可并發(fā)執(zhí)行
獨(dú)立性:進(jìn)程是能獨(dú)立運(yùn)行、獨(dú)立獲取資源、獨(dú)立接受調(diào)度的基本單位
異步性:各進(jìn)程按各自獨(dú)立的、不可預(yù)知的速度向前推進(jìn),操作系統(tǒng)要提供“進(jìn)程同步機(jī)制”來(lái)解決異步問(wèn)題。異步性會(huì)導(dǎo)致并發(fā)程序執(zhí)行結(jié)果的不確定性
結(jié)構(gòu)性:每個(gè)進(jìn)程都會(huì)配置一個(gè)PCB,從結(jié)構(gòu)上看,進(jìn)程由程序段、數(shù)據(jù)段、PCB組成
進(jìn)程的狀態(tài)與轉(zhuǎn)換、組織方式
進(jìn)程的狀態(tài)
三種基本狀態(tài):運(yùn)行態(tài)、就緒態(tài)、阻塞態(tài)
進(jìn)程正在被創(chuàng)建時(shí),它的狀態(tài)是“創(chuàng)建態(tài)”,在這個(gè)階段操作系統(tǒng)會(huì)為進(jìn)程分配資源、初始化PCB
當(dāng)進(jìn)程創(chuàng)建完成后,便進(jìn)入“就緒態(tài)”,處于就緒態(tài)的進(jìn)程已經(jīng)具備運(yùn)行條件,但由于沒有空閑CPU,就暫時(shí)不能運(yùn)行
系統(tǒng)中可能會(huì)有很多個(gè)進(jìn)程都處于就緒態(tài),當(dāng)CPU空閑時(shí),操作系統(tǒng)就會(huì)選擇一個(gè)就緒進(jìn)程,讓其在處理機(jī)上運(yùn)行
如果一個(gè)進(jìn)程此時(shí)在CPU上運(yùn)行,那么這個(gè)進(jìn)程處于“運(yùn)行態(tài)”,CPU會(huì)執(zhí)行該進(jìn)程對(duì)應(yīng)的程序(執(zhí)行指令序列)
在進(jìn)程運(yùn)行的過(guò)程中,可能會(huì)請(qǐng)求等待某個(gè)事件的發(fā)生(例如等待某種系統(tǒng)資源如打印機(jī)的分配,或者等待其他進(jìn)程的響應(yīng)),在這個(gè)事件發(fā)生之前,進(jìn)程無(wú)法繼續(xù)往下執(zhí)行,此時(shí)操作系統(tǒng)會(huì)讓這個(gè)進(jìn)程下CPU,并讓它進(jìn)入“阻塞態(tài)”
當(dāng)CPU空閑時(shí),又會(huì)選擇另一個(gè)“就緒態(tài)”進(jìn)程上CPU運(yùn)行
如果“運(yùn)行態(tài)”的時(shí)間片到或者處理機(jī)被搶占,此時(shí)又會(huì)回到“就緒態(tài)”
一個(gè)進(jìn)程可以執(zhí)行exit系統(tǒng)調(diào)用,請(qǐng)求操作系統(tǒng)終止該進(jìn)程,此時(shí)該進(jìn)程會(huì)進(jìn)入“終止態(tài)”,操作系統(tǒng)會(huì)讓該進(jìn)程下CPU,并回收內(nèi)存空間等資源,最后還要回收該進(jìn)程的PCB,當(dāng)終止進(jìn)程的工作完成后,這個(gè)進(jìn)程就徹底消失了
進(jìn)程狀態(tài)的轉(zhuǎn)換
阻塞態(tài)\rightarrow就緒態(tài)不是進(jìn)程本身能控制的,是一種被動(dòng)行為 運(yùn)行態(tài)\rightarrow阻塞態(tài)是一種進(jìn)程自身做出的主動(dòng)行為
不能直接由阻塞態(tài)\rightarrow運(yùn)行態(tài),也不能直接由就緒態(tài)\rightarrow阻塞態(tài)
單核CPU情況下,每一時(shí)刻只會(huì)有一個(gè)進(jìn)程處于運(yùn)行態(tài),多核CPU情況下,可能有多個(gè)進(jìn)程處于運(yùn)行態(tài)
進(jìn)程PCB中有一個(gè)變量state表示進(jìn)程的當(dāng)前狀態(tài)
為了對(duì)同一個(gè)狀態(tài)下的各個(gè)進(jìn)程進(jìn)程統(tǒng)一的管理,操作系統(tǒng)會(huì)將各個(gè)進(jìn)程的PCB組織起來(lái)
進(jìn)程的組織
按照進(jìn)程狀態(tài)將PCB分為多個(gè)隊(duì)列,操作系統(tǒng)持有指向各個(gè)隊(duì)列的指針
索引方式
根據(jù)進(jìn)程狀態(tài)的不同建立幾張索引表,操作系統(tǒng)持有指向各個(gè)索引表的指針
進(jìn)程控制
進(jìn)程控制的主要功能是對(duì)系統(tǒng)中的所有進(jìn)程實(shí)施有效的管理,它具有創(chuàng)建新進(jìn)程、撤銷已有進(jìn)程、實(shí)現(xiàn)進(jìn)程狀態(tài)轉(zhuǎn)換等功能 簡(jiǎn)要理解:進(jìn)程控制就是要實(shí)現(xiàn)進(jìn)程狀態(tài)轉(zhuǎn)換
如何實(shí)現(xiàn)進(jìn)程控制
用“原語(yǔ)”實(shí)現(xiàn),原語(yǔ)是一種特殊的程序,它的執(zhí)行具有原子性,這段程序的運(yùn)行必須一氣呵成,不可中斷
如果不能“一氣呵成”,就有可能導(dǎo)致操作系統(tǒng)中的某些關(guān)鍵數(shù)據(jù)結(jié)構(gòu)信息不統(tǒng)一的情況,這會(huì)影響操作系統(tǒng)進(jìn)行別的管理工作
如何實(shí)現(xiàn)原語(yǔ)的“原子性”
原語(yǔ)的執(zhí)行具有原子性,即執(zhí)行過(guò)程只能一氣呵成,期間不允許被中斷
可以用“關(guān)中斷指令”和“開中斷指令”這兩個(gè)特權(quán)指令實(shí)現(xiàn)原子性
CPU執(zhí)行了關(guān)中斷指令后就不再例行檢查中斷信號(hào),直到執(zhí)行開中斷指令后才會(huì)恢復(fù)檢查,這樣,關(guān)中斷、開中斷之間的這些指令序列就是不可被中斷的,這就實(shí)現(xiàn)了“原子性”
進(jìn)程控制相關(guān)的原語(yǔ)
進(jìn)程的創(chuàng)建相關(guān)原語(yǔ)
創(chuàng)建原語(yǔ)
申請(qǐng)空白PCB
為新進(jìn)程分配所需資源
初始化PCB
將PCB插入就緒隊(duì)列
引起進(jìn)程創(chuàng)建的事件
用戶登錄:分時(shí)系統(tǒng)中,用戶登錄成功,系統(tǒng)會(huì)為其建立一個(gè)新的進(jìn)程
作業(yè)調(diào)度:多道批處理系統(tǒng)中,由新的作業(yè)放入內(nèi)存時(shí),會(huì)為其建立一個(gè)新的進(jìn)程
提供服務(wù):用戶向操作系統(tǒng)提出某些請(qǐng)求時(shí),會(huì)新建一個(gè)進(jìn)程處理該請(qǐng)求
應(yīng)用請(qǐng)求:由用戶進(jìn)程主動(dòng)請(qǐng)求創(chuàng)建一個(gè)子進(jìn)程
進(jìn)程的終止相關(guān)原語(yǔ)
撤消原語(yǔ):使進(jìn)程從就緒態(tài)/阻塞態(tài)/運(yùn)行態(tài)\rightarrow終止態(tài)\rightarrow無(wú)
從PCB集合中找到終止進(jìn)程的PCB
若進(jìn)程正在運(yùn)行,立即剝奪CPU,將CPU分配給其他進(jìn)程
終止其所有子進(jìn)程(進(jìn)程間的關(guān)系是樹形結(jié)構(gòu))
將該進(jìn)程擁有的所有資源歸還給父進(jìn)程或操作系統(tǒng)
刪除PCB
引起進(jìn)程終止的事件
正常結(jié)束:進(jìn)程自己請(qǐng)求終止(exit系統(tǒng)調(diào)用)
異常結(jié)束:整數(shù)除以0、非法使用特權(quán)指令,然后被操作系統(tǒng)強(qiáng)行殺掉
外界干預(yù):Ctrl+Alt+delete用戶選擇殺掉進(jìn)程
進(jìn)程的阻塞相關(guān)原語(yǔ)
阻塞原語(yǔ):運(yùn)行態(tài)\rightarrow阻塞態(tài)
找到要阻塞的進(jìn)程對(duì)應(yīng)的PCB
保護(hù)進(jìn)程運(yùn)行現(xiàn)場(chǎng),將PCB狀態(tài)信息設(shè)為“阻塞態(tài)”,暫時(shí)停止進(jìn)程運(yùn)行
將PCB插入相應(yīng)事件的等待隊(duì)列
引起進(jìn)程阻塞的事件
需要等待系統(tǒng)分配某種資源
需要等待相互合作的其他進(jìn)程完成工作
進(jìn)程的喚醒相關(guān)原語(yǔ)
喚醒原語(yǔ):阻塞態(tài)\rightarrow就緒態(tài)
在事件等待隊(duì)列中找到PCB
將PCB從等待隊(duì)列中移除,設(shè)置進(jìn)程為就緒態(tài)
將PCB插入就緒隊(duì)列,等待被調(diào)度
引起進(jìn)程喚醒的事件
等待的事件發(fā)生:因何事阻塞,就應(yīng)該由何事喚醒
阻塞原語(yǔ)和喚醒原語(yǔ)必須成對(duì)使用
進(jìn)程的切換相關(guān)原語(yǔ)
切換原語(yǔ):運(yùn)行態(tài)\rightarrow就緒態(tài) 或者 就緒態(tài)\rightarrow運(yùn)行態(tài)
將運(yùn)行環(huán)境信息存入PCB
PCB移入相應(yīng)隊(duì)列
選擇另一個(gè)進(jìn)程執(zhí)行,并更新其PCB
根據(jù)PCB恢復(fù)新進(jìn)程所需的運(yùn)行環(huán)境
引起進(jìn)程切換的事件
當(dāng)前進(jìn)程時(shí)間片到
有更高優(yōu)先級(jí)的進(jìn)程到達(dá)
當(dāng)前進(jìn)程主動(dòng)阻塞
當(dāng)前進(jìn)程終止
進(jìn)程通信
進(jìn)程間通信(Inter-Process Communication,IPC)指兩個(gè)進(jìn)程之間產(chǎn)生數(shù)據(jù)交互
進(jìn)程是分配系統(tǒng)資源的單位(包括內(nèi)存地址空間),因此各進(jìn)程擁有的內(nèi)存地址空間相互獨(dú)立。為保證安全,一個(gè)進(jìn)程不能直接訪問(wèn)另一個(gè)進(jìn)程的地址空間
共享存儲(chǔ)
共享存儲(chǔ)分為兩種方式:
基于存儲(chǔ)區(qū)的共享:操作系統(tǒng)在內(nèi)存中劃出一塊共享存儲(chǔ)區(qū),數(shù)據(jù)的形式、存放位置都由通信進(jìn)程控制,而不是操作系統(tǒng)。這種共享方式速度很快,是一種高級(jí)通信方式
基于數(shù)據(jù)結(jié)構(gòu)的共享:比如共享空間只能放一個(gè)長(zhǎng)度為10的數(shù)組,這種共享方式速度慢、顯示多,是一種低級(jí)通信的方式
消息傳遞
進(jìn)程間的數(shù)據(jù)以格式化的消息為單位。進(jìn)程通過(guò)操作系統(tǒng)提供的“發(fā)送消息/接收消息”兩個(gè)原語(yǔ)進(jìn)行數(shù)據(jù)交換
消息傳遞分為兩種方式
直接通信方式:消息發(fā)送進(jìn)程要指明接收進(jìn)程的ID,點(diǎn)名道姓的消息傳遞
間接通信方式:通過(guò)“信箱”間接地通信,因此又稱“信箱通信方式”
可以多個(gè)進(jìn)程往同一個(gè)信箱send消息,也可以多個(gè)進(jìn)程從同一個(gè)信箱中receive消息
管道通信
管道采用循環(huán)隊(duì)列的方式,先進(jìn)先出,只能一端寫一端讀
管道是半雙工通信,某一時(shí)間段只能實(shí)現(xiàn)單向的數(shù)據(jù)傳輸,如果要實(shí)現(xiàn)雙向同時(shí)通信,則要設(shè)置兩個(gè)管道
當(dāng)管道寫滿時(shí),寫進(jìn)程阻塞,直到讀進(jìn)程將管道內(nèi)的數(shù)據(jù)取走即可喚醒寫進(jìn)程 當(dāng)管道讀空時(shí),讀進(jìn)程阻塞,直到寫進(jìn)程往管道中寫數(shù)據(jù),即可喚醒讀進(jìn)程
管道中的數(shù)據(jù)一旦被讀出,就徹底消失
線程的概念
沒引入進(jìn)程之前,系統(tǒng)中各個(gè)程序只能串行執(zhí)行,如不能邊聽音樂(lè)邊聊QQ,引入進(jìn)程之后才可
進(jìn)程是程序的一次執(zhí)行,有的進(jìn)程可能需要“同時(shí)”做很多事,而傳統(tǒng)的進(jìn)程只能串行地執(zhí)行一系列程序,為此引入了“線程”來(lái)增加并發(fā)度
線程是一個(gè)基本的CPU執(zhí)行單元,也是程序執(zhí)行流的最小單位
引入線程之后,不僅是進(jìn)程之間可以并發(fā),進(jìn)程內(nèi)的個(gè)線程之間也可以并發(fā),從而進(jìn)一步提升了系統(tǒng)的并發(fā)度,使得一個(gè)進(jìn)程內(nèi)也可以并發(fā)處理各種任務(wù)(如QQ視頻、文字聊天、傳文件)
引入線程后,進(jìn)程只作為除CPU之外的系統(tǒng)資源的分配單元(如打印機(jī)、內(nèi)存地址空間都是分配給進(jìn)程的)
線程的屬性
線程是處理機(jī)調(diào)度的單位
多CPU計(jì)算機(jī)中,各個(gè)線程可占用不同的CPU
每個(gè)線程都有一個(gè)線程ID、線程控制塊(TCB)
線程也有就緒、阻塞、運(yùn)行三種基本狀態(tài)
線程幾乎不擁有系統(tǒng)資源
由于共享內(nèi)存地址空間,同一進(jìn)程中的線程通信甚至無(wú)需系統(tǒng)干預(yù)
同一進(jìn)程中的線程切換,不會(huì)引起進(jìn)程切換
不同進(jìn)程中的線程切換,會(huì)引起進(jìn)程切換
切換同進(jìn)程內(nèi)的線程,系統(tǒng)開銷很小
切換進(jìn)程,系統(tǒng)開銷較大
線程的實(shí)現(xiàn)方式和多線程模型
線程的實(shí)現(xiàn)方式
用戶級(jí)線程
歷史背景:早期的操作系統(tǒng)(如早期Unix)只支持進(jìn)程,不支持線程,當(dāng)時(shí)的“線程”是由線程庫(kù)實(shí)現(xiàn)的
?int main(){
? ? ?int i=0;
? ? ?while(true){
? ? ? ? ?if(i==0){處理視頻聊天;}
? ? ? ? ?if(i==1){處理文字聊天;}
? ? ? ? ?if(i==2){處理文件傳輸;}
? ? ? ? ?i=(i+1)%3
? ? ?}
?}
從代碼的角度看,線程其實(shí)就是一段代碼邏輯,上述三段代碼邏輯上可以看做三個(gè)“線程”,while循環(huán)就是一個(gè)最簡(jiǎn)單的“線程庫(kù)”,線程庫(kù)完成了對(duì)線程的管理工作(如調(diào)度)
用戶級(jí)線程由應(yīng)用程序通過(guò)線程庫(kù)實(shí)現(xiàn),所有的線程管理工作都由應(yīng)用程序負(fù)責(zé)(包括線程切換)
用戶級(jí)線程中,線程切換可以在用戶態(tài)下即可完成,無(wú)需操作系統(tǒng)干預(yù)
在用戶看來(lái),是有多個(gè)線程,但是在操作系統(tǒng)內(nèi)核看來(lái),并不意識(shí)到線程的存在。“用戶級(jí)線程”就是“從用戶視角看能看到的線程”
優(yōu)缺點(diǎn):
優(yōu)點(diǎn):用戶級(jí)線程的切換在用戶空間即可完成,不需要切換到核心態(tài),線程管理的系統(tǒng)開銷小,效率高
缺點(diǎn):當(dāng)一個(gè)用戶級(jí)線程被阻塞后,整個(gè)進(jìn)程都會(huì)被阻塞,并發(fā)度不高,多個(gè)線程不可在多核處理機(jī)上并行運(yùn)行
內(nèi)核級(jí)線程
kernel-level Thread,又稱“內(nèi)核支持的線程”,由操作系統(tǒng)支持的線程
內(nèi)核級(jí)線程的管理工作由操作系統(tǒng)內(nèi)核完成
線程調(diào)度、切換等工作都由內(nèi)核負(fù)責(zé),因此內(nèi)核級(jí)線程的切換必然需要在核心態(tài)下才能完成
操作系統(tǒng)為每個(gè)內(nèi)核級(jí)線程建立相應(yīng)的TCB(Thread Control Block,線程控制塊),通過(guò)TCB對(duì)線程進(jìn)行管理。“內(nèi)核級(jí)線程”就是從“操作系統(tǒng)內(nèi)核視角看能看到的線程”
優(yōu)缺點(diǎn):
優(yōu)點(diǎn):當(dāng)一個(gè)線程被阻塞后,別的線程還可以繼續(xù)執(zhí)行,并發(fā)能力強(qiáng)。多線程可以在多核處理機(jī)上并行執(zhí)行
缺點(diǎn):一個(gè)用戶進(jìn)程會(huì)占用多個(gè)內(nèi)核級(jí)線程,線程切換由操作系統(tǒng)內(nèi)核完成,需要切換到核心態(tài),因此線程管理的成本高,開銷大
多線程模型
在支持內(nèi)核級(jí)線程的系統(tǒng)中,根據(jù)用戶級(jí)線程和內(nèi)核級(jí)線程的映射關(guān)系,可以劃分為幾種多線程模型
一對(duì)一模型
一個(gè)用戶級(jí)線程映射到一個(gè)內(nèi)核級(jí)線程,每個(gè)用戶進(jìn)程有與用戶級(jí)線程同數(shù)量的內(nèi)核級(jí)線程
優(yōu)點(diǎn):當(dāng)一個(gè)線程被阻塞后,別的線程還可以繼續(xù)執(zhí)行,并發(fā)能力強(qiáng),多線程可在多核處理機(jī)上并行執(zhí)行
缺點(diǎn):一個(gè)用戶進(jìn)程會(huì)占用多個(gè)內(nèi)核級(jí)線程,線程切換由操作系統(tǒng)內(nèi)核完成,需要切換到核心態(tài),因此線程管理的成本高,開銷大
多對(duì)一模型
多個(gè)用戶級(jí)線程映射到一個(gè)內(nèi)核級(jí)線程,且一個(gè)進(jìn)程只被分配一個(gè)內(nèi)核級(jí)線程
優(yōu)點(diǎn):用戶級(jí)線程的切換在用戶空間即可完成,不需要切換到核心態(tài),線程管理的系統(tǒng)開銷小,效率高
缺點(diǎn):當(dāng)一個(gè)用戶級(jí)線程被阻塞后,整個(gè)進(jìn)程都會(huì)被阻塞,并發(fā)度不高,多個(gè)線程不可在多核處理機(jī)上并行運(yùn)行
多對(duì)多模型
n個(gè)用戶及線程映射到m個(gè)內(nèi)核級(jí)線程(n\ge m)。每個(gè)用戶進(jìn)程對(duì)應(yīng)m個(gè)內(nèi)核級(jí)線程
克服了多對(duì)一模型并發(fā)度不高的缺點(diǎn)(一個(gè)阻塞全體阻塞),又克服了一對(duì)一模型中一個(gè)用戶進(jìn)程占用太多內(nèi)核級(jí)線程,開銷太大的缺點(diǎn)
線程的狀態(tài)和轉(zhuǎn)換
狀態(tài)與進(jìn)程類似
一個(gè)TCB(線程控制塊)包含如下部分
線程標(biāo)識(shí)符:TID,與PID類似
程序計(jì)數(shù)器PC:線程目前執(zhí)行到哪里
其他寄存器:線程運(yùn)行的中間結(jié)果
堆棧指針:堆棧保存函數(shù)調(diào)用信息、局部變量等
線程運(yùn)行狀態(tài):運(yùn)行、就緒、阻塞
優(yōu)先級(jí):線程調(diào)度、資源分配的參考
線程切換時(shí)需要保存和恢復(fù)的信息:程序計(jì)數(shù)器PC、其他寄存器、堆棧指針