操作系统(二): 进程与线程
操作系統(tǒng)(二): 進(jìn)程與線程
?
本章解讀
進(jìn)程管理是操作系統(tǒng)重點(diǎn)中的重點(diǎn),涵蓋了操作系統(tǒng)中大部分的知識(shí)和考點(diǎn)。其主要包括四部分:進(jìn)程與線程,處理器調(diào)度,同步與互斥,死鎖。所以我準(zhǔn)備分四個(gè)部分來(lái)解釋這四個(gè)模塊。進(jìn)程與線程部分考綱內(nèi)容如下:
1.進(jìn)程概念
2.進(jìn)程的狀態(tài)與轉(zhuǎn)換
3.進(jìn)程控制
4.進(jìn)程組織
5.進(jìn)程通信:共享存儲(chǔ)系統(tǒng);消息傳遞系統(tǒng);管道通信。
6.線程概念與多線程模型
?
正文
?
2.1 進(jìn)程的概念
???????? 2.1.1 程序的順序執(zhí)行和并發(fā)執(zhí)行
???????? 順序執(zhí)行特點(diǎn):順序性,封閉性,可再現(xiàn)性
并發(fā)執(zhí)行特點(diǎn):間斷性(制約性),失去封閉性,不可再現(xiàn)性。
前趨圖:是一個(gè)有向無(wú)循環(huán)圖,用于描述進(jìn)程之間執(zhí)行的前后關(guān)系。Pi→Pj表示在Pj開(kāi)始執(zhí)行前Pi必須完成,Pi是Pj的直接前趨,Pj是Pi的直接后繼。沒(méi)有前趨的結(jié)點(diǎn)稱(chēng)為初始節(jié)點(diǎn),沒(méi)有后繼的結(jié)點(diǎn)稱(chēng)為終止結(jié)點(diǎn)。
???????? 例題: ________是多道程序的基本特征。
A.?????制約性????? B.???? 順序性???? C.功能的封閉性???? D.運(yùn)行過(guò)程中的可再現(xiàn)性
答案:A
???????? 2.1.2 進(jìn)程的特征
???????? 結(jié)構(gòu)特征:進(jìn)程由程序段、數(shù)據(jù)段、程序控制塊(PCB)構(gòu)成。所謂的創(chuàng)建進(jìn)程,實(shí)質(zhì)上是創(chuàng)建進(jìn)程實(shí)體中的PCB;撤銷(xiāo)進(jìn)程實(shí)質(zhì)是撤銷(xiāo)進(jìn)程的PCB。
???????? 動(dòng)態(tài)性:進(jìn)程是動(dòng)態(tài)的,有一定的生命期;程序是靜態(tài)的,它只是一組有序指令的結(jié)合,并存放于某種介質(zhì)上。
???????? 并發(fā)性:多個(gè)進(jìn)程同時(shí)存在于內(nèi)存中,在同一段時(shí)間內(nèi)并發(fā)執(zhí)行。
???????? 獨(dú)立性:進(jìn)程實(shí)體是一個(gè)能獨(dú)立運(yùn)行、獨(dú)立分配資源和獨(dú)立接受調(diào)度的基本單位。
???????? 異步性:進(jìn)程按相互獨(dú)立,不可預(yù)知的速度向前推進(jìn)。
???????? 2.1.3 進(jìn)程的定義
???????? 進(jìn)程是進(jìn)程實(shí)體的運(yùn)行過(guò)程,是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。
???????? 例題:操作系統(tǒng)中,可以并行工作的基本單位是___(1)____,它也是核心調(diào)度及資源分配的基本單位,它是由____(2)____組成的,它與程序的重要區(qū)別之一是____(3)____。
???????? (1)??? A. 作業(yè)??????????? B.函數(shù)?????????????? C.進(jìn)程?????????????? D.過(guò)程
???????? (2)??? A.程序、數(shù)據(jù)和PCB???????????????????????? B.程序、數(shù)據(jù)和標(biāo)示符
?????????????????? C.程序、標(biāo)示符和PCB??????????????????? D.數(shù)據(jù)、標(biāo)示符和PCB
???????? (3)??? A.程序有狀態(tài),而它沒(méi)有?????????????? B.它有狀態(tài),而程序沒(méi)有
?????????????????? C.程序可占有資源,而它不可???? D.它能占有資源,而程序不能
???????? 答案:C A D
?
2.2 進(jìn)程的狀態(tài)與轉(zhuǎn)換
???????? 三種基本狀態(tài):就緒態(tài)(進(jìn)程已經(jīng)分配到除了CPU以外的所有必要資源),執(zhí)行態(tài)(獲得CPU資源的就緒態(tài)進(jìn)程),阻塞態(tài)(執(zhí)行態(tài)進(jìn)程因發(fā)生某事件而暫時(shí)無(wú)法執(zhí)行就變成了阻塞態(tài))。他們之間的關(guān)系如下:
?
? ? ? ? ?掛起狀態(tài):掛起狀態(tài)又稱(chēng)為靜止?fàn)顟B(tài)。引入掛起狀態(tài)的原因有:終端用戶(hù)的調(diào)試請(qǐng)求,父進(jìn)程請(qǐng)求,負(fù)荷調(diào)節(jié)的需要,操作系統(tǒng)的需要,對(duì)換的需要(物理內(nèi)存資源緊張,將內(nèi)存中阻塞態(tài)進(jìn)程置換到外存上)。掛起態(tài)分靜止就緒態(tài)和靜止阻塞態(tài),他們能分別與活動(dòng)就緒態(tài)以及活動(dòng)阻塞態(tài)進(jìn)行狀態(tài)轉(zhuǎn)換,此外當(dāng)靜止阻塞態(tài)的進(jìn)程所等待的事件發(fā)生時(shí),將從靜止阻塞態(tài)轉(zhuǎn)變成靜止就緒態(tài)。具有掛起狀態(tài)的進(jìn)程狀態(tài)圖如下:
? ? ? ? ?創(chuàng)建狀態(tài):創(chuàng)建進(jìn)程時(shí),若該進(jìn)程已經(jīng)擁有了自己的PCB,但進(jìn)程自身還未進(jìn)入主存,則稱(chēng)該狀態(tài)為創(chuàng)建狀態(tài)。
???????? 終止?fàn)顟B(tài):進(jìn)入終止?fàn)顟B(tài)的進(jìn)程以后不能再執(zhí)行,但正在操作系統(tǒng)中依然保留一個(gè)記錄,其中保存狀態(tài)碼和一些計(jì)時(shí)統(tǒng)計(jì)數(shù)據(jù),供其他進(jìn)程收集。一旦其它進(jìn)程完成了對(duì)終止?fàn)顟B(tài)進(jìn)程信息的提取之后,操作系統(tǒng)將刪除該進(jìn)程。
???????? 具有創(chuàng)建、終止、掛起狀態(tài)的進(jìn)程狀態(tài)圖如下:
?
?
2.3 進(jìn)程控制
???????? 進(jìn)程的控制包括創(chuàng)建新進(jìn)程,終止已完成或因某事件無(wú)法運(yùn)行的進(jìn)程,負(fù)責(zé)進(jìn)程狀態(tài)轉(zhuǎn)換(阻塞與喚醒,掛起與激活)。進(jìn)程控制是由操作系統(tǒng)的內(nèi)核中用原語(yǔ)來(lái)實(shí)現(xiàn)的。
???????? 原語(yǔ)的主要作用是為了實(shí)現(xiàn)進(jìn)程間通信和控制。原語(yǔ)其實(shí)是一段實(shí)現(xiàn)某種功能的程序指令,它與普通程序的區(qū)別是原語(yǔ)是原子操作,即它的功能要么全做,要么全不做,它不可能被調(diào)度程序中斷。原語(yǔ)在操作系統(tǒng)中是一個(gè)很重要的概念,后面要講的進(jìn)程間同步問(wèn)題所用到的信號(hào)量就是使用PV原語(yǔ)來(lái)實(shí)現(xiàn)的。原子操作在管態(tài)下執(zhí)行,常駐內(nèi)存。
2.3.1 進(jìn)程的創(chuàng)建
進(jìn)程之間是存在家族關(guān)系的,比如父子進(jìn)程,在Linux下可以通過(guò)調(diào)用fork函數(shù)創(chuàng)建子進(jìn)程。關(guān)于進(jìn)程間的父子關(guān)系,只需記住兩點(diǎn)即可:1、子進(jìn)程可以繼承父進(jìn)程所擁有的所有資源(打開(kāi)的文件,申請(qǐng)的緩沖區(qū)等) 2、當(dāng)撤銷(xiāo)父進(jìn)程時(shí),也必須同時(shí)撤銷(xiāo)其所有的子進(jìn)程。這和面向?qū)ο笾械睦^承思想非常相似。
???????? 進(jìn)程創(chuàng)建的事件有四類(lèi):用戶(hù)登錄,作業(yè)調(diào)度,提供服務(wù),應(yīng)用請(qǐng)求。
???????? 當(dāng)操作系統(tǒng)發(fā)現(xiàn)要求創(chuàng)建新進(jìn)程的時(shí)間后,便使用原語(yǔ)創(chuàng)建進(jìn)程,其順序如下:
?
? ? ? ? ?申請(qǐng)空白PCB:申請(qǐng)的PCB具有唯一的標(biāo)示符。
???????? 分配資源:給進(jìn)程分配程序區(qū)和數(shù)據(jù)區(qū)的內(nèi)存空間,并加載相應(yīng)資源。
???????? 初始化PCB:初始化標(biāo)識(shí)信息、處理器狀態(tài)信息、處理機(jī)控制信息等。
???????? 將新進(jìn)程插入就緒隊(duì)列:如果進(jìn)程就緒隊(duì)列能夠接納新進(jìn)程,則將新進(jìn)程插入就緒隊(duì)列。
2.3.2 進(jìn)程的終止
引起進(jìn)程的事件有三種:正常結(jié)束,異常結(jié)束,外界干預(yù)。
正常結(jié)束:程序運(yùn)行到功能完畢時(shí)正常的退出。
異常結(jié)束:越界錯(cuò)誤,保護(hù)錯(cuò),非法指令,特權(quán)指令錯(cuò),運(yùn)行超時(shí),等待超時(shí),算數(shù)運(yùn)算錯(cuò),I/O故障。
外界干預(yù):用戶(hù)或操作系統(tǒng)干預(yù),父進(jìn)程請(qǐng)求,父進(jìn)程終止。
???????? 當(dāng)發(fā)生進(jìn)程終止事件后,操作系統(tǒng)調(diào)用終止原語(yǔ),按下列過(guò)程終止進(jìn)程:1、根據(jù)被終止進(jìn)程標(biāo)示符找到其PCB,讀出進(jìn)程狀態(tài)。 2、若該進(jìn)程處在執(zhí)行態(tài),則終止該進(jìn)程的執(zhí)行。 3、若進(jìn)程有子孫進(jìn)程,終止它們。4、將被終止的進(jìn)程的全部資源歸還給其父進(jìn)程,若沒(méi)有父進(jìn)程就歸還給操作系統(tǒng)。5、將被終止進(jìn)程的PCB從所在隊(duì)列移除。
2.3.3 進(jìn)程的阻塞與喚醒
引起進(jìn)程的阻塞事件四種:請(qǐng)求系統(tǒng)服務(wù)(等待請(qǐng)求的服務(wù)和資源分配)、啟動(dòng)某種操作(等待某種操作完成,如I/O操作)、新數(shù)據(jù)尚未到達(dá)(等待進(jìn)程間、網(wǎng)絡(luò)中消息到來(lái))、無(wú)新工作可做(服務(wù)型的進(jìn)程等待新任務(wù)到來(lái))。
進(jìn)程阻塞過(guò)程:進(jìn)程調(diào)用阻塞原語(yǔ)block把自己阻塞。要被阻塞的進(jìn)程先停止執(zhí)行,即將PCB中的狀態(tài)由執(zhí)行改為阻塞,并將PCB插入阻塞隊(duì)列,然后調(diào)度程序調(diào)度其他進(jìn)程給處理器執(zhí)行。
???????? 進(jìn)程喚醒過(guò)程:當(dāng)被阻塞進(jìn)程期待的事件出現(xiàn),由有關(guān)進(jìn)程(如之前占用資源現(xiàn)在釋放的進(jìn)程)調(diào)用喚醒原語(yǔ)wakeup將等待該事件的進(jìn)程喚醒。首先把被喚醒的進(jìn)程的PCB從對(duì)應(yīng)事件的阻塞隊(duì)列中移出,將其PCB中的狀態(tài)由阻塞改為就緒,然后將該P(yáng)CB插入到就緒隊(duì)列中。
???????? 2.3.4進(jìn)程的掛起與激活
???????? 進(jìn)程的掛起:當(dāng)出現(xiàn)某個(gè)引起進(jìn)程掛起的事件(如用戶(hù)進(jìn)程請(qǐng)求將自己掛起,父進(jìn)程請(qǐng)求將某子進(jìn)程掛起等),操作系統(tǒng)調(diào)用掛起原語(yǔ)suspend將指定進(jìn)程掛起,掛起的過(guò)程:將就緒進(jìn)程掛起稱(chēng)為靜態(tài)就緒進(jìn)程,或?qū)⒆枞M(jìn)程掛起為靜止阻塞進(jìn)程。然后將該進(jìn)程的PCB復(fù)制到某指定的內(nèi)存區(qū)域,以方便用戶(hù)或父進(jìn)程查看該進(jìn)程的運(yùn)行情況。
???????? 進(jìn)程的激活:當(dāng)發(fā)生激活進(jìn)程的事件時(shí),如父進(jìn)程或用戶(hù)進(jìn)程請(qǐng)求激活對(duì)應(yīng)進(jìn)程,若該進(jìn)程駐留在外存,而內(nèi)存已有足夠空間,則可將外存上的進(jìn)程換入內(nèi)存。操作系統(tǒng)調(diào)用激活原語(yǔ)active激活指定進(jìn)程。首先將進(jìn)程從外存調(diào)入內(nèi)存,然后將進(jìn)程的狀態(tài)從靜止就緒/靜止阻塞轉(zhuǎn)變成(活動(dòng))就緒態(tài)/(活動(dòng))阻塞態(tài)。若采用的是搶占調(diào)度策略,每當(dāng)有新進(jìn)程進(jìn)入就緒隊(duì)列時(shí),會(huì)將新進(jìn)入的進(jìn)程和當(dāng)前執(zhí)行的進(jìn)程比較,若新進(jìn)入進(jìn)程優(yōu)先級(jí)大,這把處理器資源分給新進(jìn)入的進(jìn)程。
?
2.4 進(jìn)程的組織
2.4.1 進(jìn)程管理塊(PCB Process Control Block)
???????? 對(duì)PCB的介紹在前面已經(jīng)提到了,它其實(shí)是一個(gè)數(shù)據(jù)結(jié)構(gòu),在PCB中記錄了操作系統(tǒng)所需的、用于描述進(jìn)程的當(dāng)前情況以及控制進(jìn)程運(yùn)行的全部信息。操作系統(tǒng)就是根據(jù)PCB來(lái)對(duì)并發(fā)執(zhí)行的進(jìn)程進(jìn)行控制和管理的。PCB是進(jìn)程存在的惟一標(biāo)識(shí)。
???????? 下圖為PCB大致包括的內(nèi)容:
?
? ? ? ? ?2.4.2 進(jìn)程控制塊的組織方式
???????? 即如何將整個(gè)系統(tǒng)中成千上萬(wàn)的PCB管理組織起來(lái),方法分為鏈接方式和索引方法兩種。
?
鏈接方式
?
索引方式
? ? ? ? ?蝶叔我以前有寫(xiě)過(guò)一個(gè)以Linux作為平臺(tái)的進(jìn)程調(diào)度模擬器,其中關(guān)于PCB的組織方式就是利用類(lèi)似于索引的方式進(jìn)行,區(qū)別在于我將就緒隊(duì)列按照優(yōu)先級(jí)分為多個(gè)隊(duì)列,不同的進(jìn)程的PCB指針也就放在不同的就緒索引表里。這樣,在處理器進(jìn)行調(diào)度時(shí),每次都從優(yōu)先級(jí)高至低的順序取出一個(gè)進(jìn)程進(jìn)行調(diào)度,這樣就可以避免進(jìn)程的饑餓了。
?
2.5 進(jìn)程的通訊
???????? 本來(lái)這里將介紹進(jìn)程間同步的問(wèn)題,但由于進(jìn)程同步是考試中的重點(diǎn)加難點(diǎn)(常作為一道大題),所以準(zhǔn)備放在后面進(jìn)行專(zhuān)門(mén)的講解。現(xiàn)在先介紹進(jìn)程間的通訊問(wèn)題。
???????? 2.5.1 進(jìn)程通信的概念
???????? 進(jìn)程通信,指的進(jìn)程之間的信息交換。進(jìn)程通信分為低級(jí)通信和高級(jí)通信。進(jìn)程的同步和互斥(信號(hào)量)就是低級(jí)通信,它本質(zhì)上是使用原語(yǔ)操作共享內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)的過(guò)程,效率低(不能用來(lái)傳輸大量數(shù)據(jù)信息)并且對(duì)用戶(hù)不透明(所以才出現(xiàn)了考試信號(hào)量那道大題,哈哈)。進(jìn)程間的高級(jí)通訊有共享內(nèi)存、消息隊(duì)列、管道、套接字等等,其中套接字不僅可用在本機(jī)通訊,還可用作網(wǎng)絡(luò)通訊。
???????? 2.5.2 共享內(nèi)存系統(tǒng)(共享存儲(chǔ)器系統(tǒng) Shared-Memory System)
???????? 相互通訊的進(jìn)程可以通過(guò)共享某個(gè)內(nèi)存區(qū)域,從而實(shí)現(xiàn)用該內(nèi)存區(qū)域進(jìn)行通訊。信號(hào)量是共享內(nèi)存的一個(gè)特殊情況,信號(hào)量就只是共享了一個(gè)數(shù)據(jù)結(jié)構(gòu)的內(nèi)存。此外,高級(jí)通訊中的共享內(nèi)存,先向系統(tǒng)申請(qǐng)一個(gè)共享內(nèi)存的區(qū)域,并分配相應(yīng)的關(guān)鍵字。若其他進(jìn)程要訪問(wèn)共享內(nèi)存,則提供這個(gè)關(guān)鍵字,若存在關(guān)鍵字對(duì)應(yīng)的共享內(nèi)存區(qū)域,則返回其描述符。
???????? 在Linux 中,使用shmget、shmat、shmdt、shmctl這四個(gè)函數(shù)操作共享內(nèi)存,這里主要介紹前兩個(gè)函數(shù)。
???????? shmget用來(lái)創(chuàng)建或獲得一個(gè)共享內(nèi)存對(duì)象:
???????? #define MY_SHM_ID 67480
???????? intfd_shm;
???????? fd_shm= shmget(MY_SHM_ID, 4096, 0666 | IPC_CREAT);
???????? MY_SHM_ID是共享內(nèi)存的關(guān)鍵字,若為0則為私有內(nèi)存,常用于父子進(jìn)程通信,若不為0則用于多進(jìn)程通信。4096表示共享內(nèi)存大小為4KB,第三個(gè)參數(shù)是共享內(nèi)存的權(quán)限,如果該共享內(nèi)存不存在則創(chuàng)建。
???????? 在其他進(jìn)程中,若想訪問(wèn)這個(gè)共享內(nèi)存,則fd_shm = shmget(MY_SHM_ID, 0, 0);因?yàn)樵摴蚕韮?nèi)存已存在,函數(shù)會(huì)返回共享內(nèi)存的標(biāo)識(shí)符。
???????? 接著,使用shmat把共享內(nèi)存區(qū)對(duì)象映射到調(diào)用進(jìn)程的地址空間:
???????? void* pshm;
???????? pshm= shmat(fd_shm, NULL, 0);
???????? 其它兩個(gè)函數(shù)shmdt(斷開(kāi)共享內(nèi)存連接),shmctl(共享內(nèi)存管理)在這里介紹沒(méi)有多大意義,介紹這些知識(shí)是給大家一個(gè)對(duì)共享內(nèi)存更直觀的認(rèn)識(shí)。
???????? 2.5.3 消息傳遞系統(tǒng)(Message passing system)
???????? 消息傳遞系統(tǒng)是當(dāng)前應(yīng)用最為廣泛的進(jìn)程通信機(jī)制,消息隊(duì)列和套接字都是基于這種機(jī)制工作的。此外,在微內(nèi)核操作系統(tǒng)中,內(nèi)核和服務(wù)器進(jìn)程之間的通信都采用了消息傳遞機(jī)制。
???????? 消息傳遞可以分為直接通信和間接通信,它們的區(qū)別在于直接通信沒(méi)有緩沖區(qū),間接通信有緩沖區(qū)。直接通信中,源進(jìn)程將消息直接發(fā)往目標(biāo)進(jìn)程;間接通信中,進(jìn)程通信的消息都放在緩沖區(qū)(信箱)中。信箱又分三類(lèi):私用信箱(其他進(jìn)程只能發(fā)送消息到信箱,信箱擁有者可以讀取信息)、公用信箱(由操作系統(tǒng)創(chuàng)建,提供給批準(zhǔn)的進(jìn)程使用,這些進(jìn)程可對(duì)信箱進(jìn)行讀寫(xiě))、共享信箱(由某進(jìn)程創(chuàng)建,創(chuàng)建時(shí)指明共享進(jìn)程的名字,這樣擁有者和共享者都能對(duì)信箱讀寫(xiě))。
???????? 由于網(wǎng)絡(luò)通訊就是基于消息傳遞機(jī)制的,所以消息傳遞系統(tǒng)中的通信鏈路、消息格式其實(shí)就對(duì)應(yīng)計(jì)算機(jī)網(wǎng)絡(luò)中的數(shù)據(jù)鏈路層和網(wǎng)絡(luò)層。比如,消息傳遞系統(tǒng)的通信鏈路分點(diǎn)對(duì)點(diǎn)傳輸和多點(diǎn)連接鏈路(廣播)兩類(lèi),通信方式也可分為單向通信鏈路(單工)和雙向鏈路(全雙工),消息格式由消息頭和消息正文組成。
???????? 在Linux 中,使用msgget 、msgsnd、msgrcv、msgctl四個(gè)函數(shù)操作消息隊(duì)列。
???????? msgget用來(lái)創(chuàng)建或獲得消息隊(duì)列:
???????? #defineMY_MSG_ID 52134
???????? msgget(MY_MSG_ID,IPC_CREAT);打開(kāi)關(guān)鍵字為MY_MSG_ID的消息隊(duì)列,如果不存在則創(chuàng)建,返回消息隊(duì)列的標(biāo)識(shí)符。
???????? msgsnd和msgrcv分別對(duì)應(yīng)消息的發(fā)送和接收。
???????? msgctl函數(shù)用來(lái)對(duì)消息隊(duì)列進(jìn)行控制和刪除。
???????? 2.5.4 管道通信(pipe)
???????? 管道是用于連接一個(gè)讀進(jìn)程和一個(gè)寫(xiě)進(jìn)程以實(shí)現(xiàn)他們之間通信的一個(gè)共享文件。當(dāng)一個(gè)進(jìn)程對(duì)管道進(jìn)行操作時(shí)其它進(jìn)程必須等待。只有確定了對(duì)方已存在的時(shí)候才進(jìn)行通訊。
???????? 在Linux 中,用pipe函數(shù)創(chuàng)建匿名管道,用mkpipe函數(shù)創(chuàng)建命名管道,命名管道以文件的形式在對(duì)應(yīng)目錄下存在,用戶(hù)可以查看到它,不過(guò)命名管道文件并非真正的文件,它存在于內(nèi)存而非外存,這是通過(guò)虛擬文件系統(tǒng)(VFS)來(lái)實(shí)現(xiàn)的,所以對(duì)管道的操作可以使用低級(jí)文件操作,即open,read,write,close。
2.6 線程
???????? 2.6.1 線程的概念
???????? 線程引入的目的:進(jìn)程由于自身占有著資源,在處理器進(jìn)行調(diào)度時(shí)為了實(shí)現(xiàn)現(xiàn)場(chǎng)保護(hù)要進(jìn)行較大的開(kāi)銷(xiāo)。所以,引入線程,是為了減少程序在并發(fā)執(zhí)行時(shí)所付出的時(shí)間和空間上的開(kāi)銷(xiāo)。
???????? 線程具有許多傳統(tǒng)進(jìn)程的特點(diǎn),故線程又稱(chēng)為輕型進(jìn)程;傳統(tǒng)進(jìn)程稱(chēng)為重型進(jìn)程。在引入了線程的操作系統(tǒng)中,一個(gè)進(jìn)程至少由一個(gè)線程組成。
???????? 線程與進(jìn)程的區(qū)別
???????? 1)調(diào)度:線程是處理器調(diào)度和分派的基本單位,進(jìn)程作為資源擁有的基本單位。
???????? 2)并發(fā)性:引入線程之后,不僅僅進(jìn)程之間可以并發(fā)執(zhí)行,而且在一個(gè)進(jìn)程中的多個(gè)線程之間也可以并發(fā)執(zhí)行。在多處理器環(huán)境下,多個(gè)處理器同時(shí)也不能執(zhí)行多個(gè)進(jìn)程,而是多處理器同時(shí)執(zhí)行同一進(jìn)程中的多個(gè)線程。
???????? 3)擁有資源:一般情況線程不擁有獨(dú)立的資源,而是共享該進(jìn)程中的資源。
???????? 4)系統(tǒng)開(kāi)銷(xiāo):線程的切換只需保存和設(shè)置少量的寄存器,不涉及現(xiàn)場(chǎng)保護(hù)操作,就切換代價(jià)而言線程遠(yuǎn)高于進(jìn)程。
???????? 綜上所述,進(jìn)程的屬性有:輕型實(shí)體,獨(dú)立調(diào)度和分派的單位,可并發(fā)執(zhí)行,共享進(jìn)程資源。
???????? 線程控制塊(TCB)類(lèi)似于PCB,但它是輕型的,保存了線程的狀態(tài)參數(shù),如寄存器狀態(tài),堆棧指針,線程運(yùn)行狀態(tài),優(yōu)先級(jí),專(zhuān)有存儲(chǔ)器,信號(hào)屏蔽等。其中線程的運(yùn)行狀態(tài)只有三個(gè)基本狀態(tài):執(zhí)行、就緒、阻塞。
???????? 進(jìn)程的創(chuàng)建和終止:在Linux 中,創(chuàng)建線程使用pthread_create,終止進(jìn)程使用pthread_exit函數(shù)。值得注意的是,非分離線程終止后并不會(huì)立即釋放它的資源,而我們創(chuàng)建線程默認(rèn)的都是非分離線程。所以,如果我們現(xiàn)在有這樣一個(gè)線程:
???????? voidfunc_thread(void *arg)
???????? {
?????????????????? //什么也不做
?????????????????? pthread_exit();
???????? }
????????
???????? 如果用以下偽代碼創(chuàng)建線程:
???????? for(inti = 1 to 10000)
?????????????????? pthread_create(func_thread);
???????? 會(huì)發(fā)現(xiàn)系統(tǒng)不崩潰也殘廢,這就印證上面的說(shuō)法。如果要讓線程執(zhí)行完畢后回收資源,則需要在調(diào)用者線程執(zhí)行“等待線程終止”的命令,這個(gè)命令在Linux 為pthread_join函數(shù)。它會(huì)阻塞當(dāng)前線程直到要等待的線程結(jié)束,然后回收它的資源。當(dāng)然想讓線程執(zhí)行結(jié)束都自動(dòng)回收其資源,可以在調(diào)用者線程中將創(chuàng)建的線程設(shè)為分離線程,使用pthread_detach或者pthread_attr_setdetachstate函數(shù)。
???????? 什么叫分離線程?分離線程即分離狀態(tài)(detached)的線程,與其相反的就是結(jié)合態(tài)(非分離態(tài) joinable)。我們知道線程共享進(jìn)程的所有資源,那這個(gè)資源也就包括其它線程的信息,為了保證線程退出后其資源(如打開(kāi)的文件,線程執(zhí)行的狀態(tài)記錄等)可能會(huì)被其它線程用到,線程執(zhí)行結(jié)束后相關(guān)的資源是不會(huì)自動(dòng)回收的,這就是線程默認(rèn)的結(jié)合態(tài)(可以理解為和其它線程結(jié)合在一起,不能隨意回收資源)。要想線程執(zhí)行結(jié)束后自動(dòng)回收資源,就需要將線程指明為分離態(tài)。關(guān)于線程的分離態(tài)和結(jié)合態(tài),大家可以看下這篇文章:
???????? http://www.cnblogs.com/mydomain/archive/2011/08/14/2138454.html
???????? 2.6.2 線程的同步和通信
???????? 多線程操作系統(tǒng)中提供多種同步機(jī)制,如互斥鎖,條件變量,信號(hào)量等等。詳細(xì)的內(nèi)容在后面會(huì)慢慢介紹。這里說(shuō)一下條件變量:
???????? 如果只是用互斥鎖,當(dāng)線程A占有資源A想要資源B,線程B占有資源B想要資源A時(shí),就會(huì)出現(xiàn)死鎖。解決方法就是使用條件變量,因?yàn)榫€程A想要資源B時(shí),資源A此時(shí)是線程A不會(huì)用到的,所以只要將它釋放掉即可。條件變量就起到標(biāo)記資源的狀態(tài)的作用,通過(guò)互斥鎖來(lái)改變條件變量進(jìn)行資源的占有和釋放。
???????? 2.6.3 線程的實(shí)現(xiàn)方式
???????? 線程的實(shí)現(xiàn)方式分三種:內(nèi)核支持線程(KST kernel Supported Threads)、用戶(hù)級(jí)線程(ULT User Level Threads)、內(nèi)核線程和用戶(hù)線程的組合。
???????? 內(nèi)核支持線程:即線程是在內(nèi)核的支持下運(yùn)行的,無(wú)論用戶(hù)級(jí)線程還是內(nèi)核中的線程,他們的創(chuàng)建、撤銷(xiāo)和調(diào)度都是內(nèi)核來(lái)進(jìn)行的。它的優(yōu)點(diǎn):多個(gè)線程可以并行執(zhí)行在多個(gè)處理器上;當(dāng)一個(gè)線程阻塞時(shí),操作系統(tǒng)會(huì)調(diào)度其他線程占有處理器;內(nèi)核里的線程速度快開(kāi)銷(xiāo)小。但缺點(diǎn)是用戶(hù)級(jí)線程的操作需要從用戶(hù)態(tài)進(jìn)入到內(nèi)核態(tài),開(kāi)銷(xiāo)較大。
???????? 用戶(hù)級(jí)線程:線程存在于用戶(hù)空間里,對(duì)線程的創(chuàng)建、撤銷(xiāo)和調(diào)度等操作都不需要系統(tǒng)調(diào)用。也就是說(shuō),就算系統(tǒng)內(nèi)核不支持多線程,用戶(hù)空間里的進(jìn)程也可以擁有多線程。由于不會(huì)涉及到系統(tǒng)調(diào)用,并且線程調(diào)度比進(jìn)程調(diào)度來(lái)的簡(jiǎn)單,所以使得線程切換的速度特別快。值得指出的是,用戶(hù)級(jí)線程其實(shí)是將系統(tǒng)分給每個(gè)進(jìn)程的時(shí)間片再進(jìn)行時(shí)分復(fù)用的,比如一個(gè)進(jìn)程的時(shí)間片為1,它有100個(gè)用戶(hù)級(jí)線程,那么每個(gè)線程的時(shí)間只有1/100。用戶(hù)級(jí)線程的優(yōu)點(diǎn)就是節(jié)約了模式切換的開(kāi)銷(xiāo)和內(nèi)核的資源;靈活性高,不同進(jìn)程可以選擇不同的線程調(diào)度算法;用戶(hù)級(jí)線程的實(shí)現(xiàn)與操作系統(tǒng)平臺(tái)無(wú)關(guān),操作系統(tǒng)不知道用戶(hù)級(jí)線程的存在,可以在不支持多線程的操作系統(tǒng)運(yùn)行。但用戶(hù)級(jí)線程有兩個(gè)很大的缺點(diǎn):一是當(dāng)一個(gè)線程阻塞時(shí),整個(gè)進(jìn)程中所有的線程也就阻塞了。二是在多處理器平臺(tái)上不能實(shí)現(xiàn)多線程在多處理器上并行執(zhí)行。
???????? 組合方式:其實(shí)就是將內(nèi)核支持線程和用戶(hù)級(jí)線程結(jié)合在一起,取長(zhǎng)補(bǔ)短,實(shí)現(xiàn)了內(nèi)核支持線程的功能,又保證用戶(hù)級(jí)線程調(diào)度的快速。
???????? 2.6.4 線程的實(shí)現(xiàn)
???????? 1)內(nèi)核支持線程的實(shí)現(xiàn)
???????? 系統(tǒng)在創(chuàng)建一個(gè)新進(jìn)程時(shí),內(nèi)核會(huì)為它分配一個(gè)任務(wù)數(shù)據(jù)區(qū)PTDA(Per Task Data Area),其中包括了若干線程的線程控制塊TCB,操作系統(tǒng)內(nèi)核通過(guò)這些TCB來(lái)分辨線程。
???????? 2)用戶(hù)級(jí)線程的實(shí)現(xiàn)
???????? 用戶(hù)級(jí)線程在用戶(hù)空間實(shí)現(xiàn),但它們都運(yùn)行在一個(gè)中間系統(tǒng)之上。中間系統(tǒng)有兩種,運(yùn)行時(shí)系統(tǒng)和內(nèi)核控制線程。
???????? 運(yùn)行時(shí)系統(tǒng)(Runtime System):它實(shí)質(zhì)上是用于管理和控制線程的函數(shù)的集合,其中包括創(chuàng)建、撤銷(xiāo)、調(diào)度線程等操作的函數(shù)。用戶(hù)級(jí)線程的操作不會(huì)直接使用系統(tǒng)調(diào)用,而是將相關(guān)的請(qǐng)求發(fā)給運(yùn)行時(shí)系統(tǒng),由運(yùn)行時(shí)系統(tǒng)進(jìn)行相關(guān)系統(tǒng)調(diào)用來(lái)和內(nèi)核交流。
???????? 內(nèi)核控制線程:這種線程又稱(chēng)為輕型線程LWP(Light Weight Process)。這是內(nèi)核支持線程和用戶(hù)級(jí)線程的組合方式中的線程調(diào)度,將一個(gè)用戶(hù)級(jí)線程連接到LWP上,該用戶(hù)線程就具有了內(nèi)核支持線程的所有屬性。如下圖:
?
? ? ? ? ?內(nèi)核相當(dāng)于一個(gè)服務(wù)器,而內(nèi)核線程就對(duì)應(yīng)了內(nèi)核的各種功能性的服務(wù)。用戶(hù)級(jí)線程可以通過(guò)LWP來(lái)訪問(wèn)內(nèi)核,內(nèi)核不知道用戶(hù)級(jí)線程的存在,內(nèi)核只能看到LWP。由于LWP數(shù)量有限,常常將LWP做成線程池,使多個(gè)用戶(hù)級(jí)線程多路復(fù)用一個(gè)LWP。
???????? 用戶(hù)級(jí)線程可以獨(dú)立于內(nèi)核運(yùn)行,與內(nèi)核無(wú)關(guān)。也就是說(shuō),當(dāng)用戶(hù)級(jí)線程不需要與內(nèi)核通信時(shí),并不需要LWP;當(dāng)要通信時(shí),就需要借助LWP,并且一個(gè)要通信的用戶(hù)級(jí)線程就對(duì)應(yīng)一個(gè)LWP。再說(shuō)明白點(diǎn),LWP就是內(nèi)核線程提供給用戶(hù)級(jí)線程訪問(wèn)內(nèi)核的一個(gè)接口。
???????? 那么我們就要思考了,傳統(tǒng)內(nèi)核支持線程中的用戶(hù)級(jí)線程和使用結(jié)合方式下的用戶(hù)級(jí)線程有什么區(qū)別呢?內(nèi)核支持線程中的用戶(hù)線程的所有操作(創(chuàng)建、撤銷(xiāo)、調(diào)度、通信等)都需要經(jīng)過(guò)內(nèi)核,那么這里的用戶(hù)態(tài)和內(nèi)核態(tài)的切換需要花費(fèi)很多時(shí)間;而結(jié)合方式里,引入了LWP,在平常情況(不訪問(wèn)內(nèi)核)下,用戶(hù)級(jí)線程跟操作系統(tǒng)無(wú)關(guān),是通過(guò)時(shí)分復(fù)用進(jìn)程的時(shí)間片來(lái)工作的,當(dāng)需要訪問(wèn)內(nèi)核與內(nèi)核通信時(shí),用戶(hù)級(jí)線程連接到一個(gè)LWP上,通過(guò)LWP與內(nèi)核通信。這樣,結(jié)合方式下的用戶(hù)級(jí)線程在平常的調(diào)度等操作不需要訪問(wèn)內(nèi)核,加快了執(zhí)行效率,當(dāng)需要訪問(wèn)內(nèi)核時(shí)通過(guò)LWP來(lái)實(shí)現(xiàn)與內(nèi)核通信,這樣實(shí)現(xiàn)了揚(yáng)長(zhǎng)避短。
???????? 所以,下面兩句話都是正確的:
???????? 1> 在內(nèi)核級(jí)線程執(zhí)行操作時(shí),如果發(fā)生阻塞,則與之相連接的多個(gè)LWP也將隨之阻塞,進(jìn)而使連接到LWP上的用戶(hù)級(jí)線程也被阻塞。如果進(jìn)程只包含一個(gè)LWP,則此時(shí)進(jìn)程應(yīng)阻塞。
???????? 2> 若進(jìn)程包含多個(gè)LWP,當(dāng)一個(gè)LWP阻塞時(shí),進(jìn)程中另一個(gè)LWP可繼續(xù)執(zhí)行;就算進(jìn)程中所有的LWP全部阻塞,進(jìn)程中的線程也依然能繼續(xù)執(zhí)行,只是不能再訪問(wèn)內(nèi)核了。
???????? 想要了解更多的朋友可以看下這個(gè)鏈接:
???????? http://blog.163.com/jiams_wang/blog/static/303391492012103010374038/
?
???????? 由于時(shí)間倉(cāng)促,后面的內(nèi)容就沒(méi)有找習(xí)題了,相關(guān)教材參考書(shū)和網(wǎng)上有很多習(xí)題,大家自行找找。
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/jiangu66/p/3217685.html
總結(jié)
以上是生活随笔為你收集整理的操作系统(二): 进程与线程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: LIBCMTD.lib与libcpmtd
- 下一篇: 使用BAT批处理执行sql