第二章 進(jìn)程的描述與控制

第二章 進(jìn)程的描述與控制

前趨圖和程序執(zhí)行

程序的順序執(zhí)行

單道程序設(shè)計(jì) -> 程序的順序執(zhí)行

在程序順序執(zhí)行時(shí)庭惜,具有這樣三個(gè)特征:

  1. 順序性:處理機(jī)嚴(yán)格按照程序所規(guī)定的順序執(zhí)行丰泊,即每一操作必須在下一操作開始之前結(jié)束赦邻;
  2. 封閉性:程序在封閉的環(huán)境下運(yùn)行,獨(dú)占全機(jī)資源囚霸,資源的狀態(tài)(除初始狀態(tài)外)只有本程序才能改變瞧省,程序一旦開始執(zhí)行其結(jié)果就不受外界影響;
  3. 可再現(xiàn)性:只要程序執(zhí)行時(shí)的環(huán)境和初始條件相同累澡,程序重復(fù)執(zhí)行時(shí)就可以獲得相同的結(jié)果梦抢。

程序的并發(fā)執(zhí)行

多道程序設(shè)計(jì) -> 程序的并發(fā)執(zhí)行

程序并發(fā)執(zhí)行時(shí)雖然提高了系統(tǒng)的吞吐量和資源利用率,但由于它們共享系統(tǒng)資源愧哟,以及它們?yōu)橥瓿梢豁?xiàng)任務(wù)而相互合作奥吩,致使這些并發(fā)執(zhí)行的程序之間形成互相制約的關(guān)系,給程序的并發(fā)執(zhí)行帶來新特征:

  1. 間斷性:程序在并發(fā)執(zhí)行時(shí)由于共享系統(tǒng)資源以及為完成同一項(xiàng)任務(wù)而相互合作蕊梧,致使這些程序之間形成了相互制約的關(guān)系霞赫,相互制約導(dǎo)致并發(fā)程序具有“執(zhí)行——暫停——執(zhí)行”這種間斷性的活動(dòng)規(guī)律肥矢;
  2. 失去封閉性:當(dāng)系統(tǒng)中存在多個(gè)并發(fā)執(zhí)行的程序時(shí)端衰,系統(tǒng)中的各種資源將為它們所共享,這些資源的狀態(tài)也由這些程序來改變甘改,致使其中任一程序在運(yùn)行時(shí)其環(huán)境都會(huì)受到其它程序的影響旅东;
  3. 不可再現(xiàn)性:程序在并發(fā)執(zhí)行時(shí)由于失去了封閉性,其計(jì)算結(jié)果必將與并發(fā)程序的執(zhí)行速度有關(guān)十艾,也將導(dǎo)致其又失去可再現(xiàn)性抵代。

進(jìn)程的描述

進(jìn)程的定義和特征

進(jìn)程的定義

PCB:為了使參與并發(fā)執(zhí)行的每個(gè)程序(含數(shù)據(jù))都能獨(dú)立運(yùn)行,在操作系統(tǒng)中必須為之配置一個(gè)專門的數(shù)據(jù)結(jié)構(gòu)疟羹,稱為進(jìn)程控制塊(Process Control Block主守,PCB)禀倔。系統(tǒng)利用PCB來描述進(jìn)程的基本情況和活動(dòng)過程,進(jìn)而管理和控制進(jìn)程参淫。

注意:PCB是進(jìn)程存在的唯一定義救湖。

進(jìn)程實(shí)體:又稱進(jìn)程映像,由程序段涎才、相關(guān)數(shù)據(jù)段和PCB三部分構(gòu)成鞋既,一般情況下把進(jìn)程實(shí)體簡稱為進(jìn)程链沼。

進(jìn)程的定義:進(jìn)程是進(jìn)程實(shí)體的運(yùn)行過程茅诱,是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。

注意:嚴(yán)格來說進(jìn)程實(shí)體和進(jìn)程不同:進(jìn)程實(shí)體是靜態(tài)的昼蛀,進(jìn)程是動(dòng)態(tài)的棕兼。如果不專門考察兩者的區(qū)別就可以認(rèn)為“進(jìn)程實(shí)體就是進(jìn)程”陡舅,也可以說:進(jìn)程由程序段、數(shù)據(jù)段伴挚、PCB三部分組成靶衍。

進(jìn)程的特征

  1. 結(jié)構(gòu)性:每個(gè)進(jìn)程都會(huì)配置一個(gè)PCB,進(jìn)程具有程序所沒有的PCB結(jié)構(gòu)茎芋,進(jìn)程由程序段颅眶、數(shù)據(jù)段、PCB三部分組成田弥;
  2. 動(dòng)態(tài)性:進(jìn)程的實(shí)質(zhì)是進(jìn)程實(shí)體的執(zhí)行過程涛酗,動(dòng)態(tài)性是進(jìn)程最基本的特征;
  3. 并發(fā)性:多個(gè)進(jìn)程實(shí)體同時(shí)存在于內(nèi)存中偷厦,且能在一段時(shí)間內(nèi)同時(shí)運(yùn)行商叹;
  4. 獨(dú)立性:進(jìn)程實(shí)體是一個(gè)能獨(dú)立運(yùn)行、獨(dú)立獲得資源和獨(dú)立接受調(diào)度的基本單位只泼;
  5. 異步性:進(jìn)程是按異步方式運(yùn)行的沈自,即按各自獨(dú)立的、不可預(yù)知的速度向前推進(jìn)辜妓。

進(jìn)程的基本狀態(tài)及其轉(zhuǎn)換

進(jìn)程的三種基本狀態(tài)

  1. 就緒:進(jìn)程已分配到除CPU以外的所有必要資源枯途,只要再獲得CPU便可立即執(zhí)行;
  2. 執(zhí)行:進(jìn)程已經(jīng)獲得CPU籍滴,其程序正在執(zhí)行酪夷;
  3. 阻塞:正在執(zhí)行的進(jìn)程由于發(fā)生某事件(如I/O請求、申請緩沖區(qū)失敗等)暫時(shí)無法繼續(xù)執(zhí)行孽惰。

創(chuàng)建狀態(tài)和終止?fàn)顟B(tài)

  1. 創(chuàng)建狀態(tài):進(jìn)程正在被創(chuàng)建晚岭,操作系統(tǒng)為進(jìn)程分配資源、初始化PCB勋功;
  2. 終止?fàn)顟B(tài):進(jìn)程正在被撤銷坦报,操作系統(tǒng)會(huì)回收進(jìn)程擁有的資源库说,撤銷PCB。

基本狀態(tài)的轉(zhuǎn)換

image

掛起操作和進(jìn)程狀態(tài)的轉(zhuǎn)換

掛起操作的引入

  • 終端用戶的需要:便于用戶研究自己的程序的執(zhí)行情況或?qū)Τ绦蜻M(jìn)行修改片择;
  • 父進(jìn)程請求:父進(jìn)程希望暫停子進(jìn)程潜的,以便考察和修改該子進(jìn)程或協(xié)調(diào)各子進(jìn)程之間的活動(dòng);
  • 負(fù)荷調(diào)節(jié)的需要:當(dāng)實(shí)時(shí)系統(tǒng)中的工作負(fù)荷較重時(shí)可以把一些不重要的進(jìn)程掛起字管,以保證系統(tǒng)的正常運(yùn)行啰挪;
  • 操作系統(tǒng)的需要:便于操作系統(tǒng)檢查運(yùn)行中的資源使用情況或進(jìn)行記賬。

引入掛起操作后進(jìn)程狀態(tài)的轉(zhuǎn)換

  • 創(chuàng)建->活動(dòng)就緒:在當(dāng)前系統(tǒng)的性能和內(nèi)存容量均允許的狀態(tài)下創(chuàng)建進(jìn)程嘲叔;
  • 創(chuàng)建->靜止就緒:不分配給新進(jìn)程所需資源(主要是內(nèi)存)亡呵,進(jìn)程被安置在外存不參與調(diào)度,進(jìn)程的創(chuàng)建工作尚未完成硫戈;
  • 活動(dòng)就緒->靜止就緒:進(jìn)程處于未被掛起的就緒狀態(tài)時(shí)被掛起锰什,不參與調(diào)度;
  • 靜止就緒->活動(dòng)就緒:靜止就緒狀態(tài)的進(jìn)程被激活丁逝,參與調(diào)度歇由;
  • 活動(dòng)阻塞->靜止阻塞:進(jìn)程處于未被掛起的阻塞狀態(tài)時(shí)被掛起;
  • 靜止阻塞->靜止就緒:靜止阻塞的進(jìn)程所期待的事件出現(xiàn)果港;
  • 靜止阻塞->活動(dòng)阻塞:靜止阻塞狀態(tài)的進(jìn)程被激活。

進(jìn)程管理中的數(shù)據(jù)結(jié)構(gòu)

操作系統(tǒng)中用于管理控制的數(shù)據(jù)結(jié)構(gòu)

在計(jì)算機(jī)系統(tǒng)中糊昙,對于每個(gè)資源和每個(gè)進(jìn)程都設(shè)置了一個(gè)數(shù)據(jù)結(jié)構(gòu)辛掠,用于表征其實(shí)體,稱為資源信息表或進(jìn)程信息表释牺。OS管理的這些數(shù)據(jù)結(jié)構(gòu)一般分為內(nèi)存表萝衩、設(shè)備表、文件表和用于進(jìn)程管理的進(jìn)程表没咙,通常進(jìn)程表又被稱為進(jìn)程控制塊PCB猩谊。

PCB的作用

PCB的作用是使一個(gè)在多道程序環(huán)境下不能獨(dú)立運(yùn)行的程序(含數(shù)據(jù))稱為一個(gè)能獨(dú)立運(yùn)行的基本單位,一個(gè)能與其他進(jìn)程并發(fā)執(zhí)行的進(jìn)程祭刚。

  • 作為獨(dú)立運(yùn)行的基本標(biāo)志
  • 能實(shí)現(xiàn)間斷性運(yùn)行方式
  • 提供進(jìn)程管理所需要的信息
  • 提供進(jìn)程調(diào)度所需要的信息
  • 實(shí)現(xiàn)與其他進(jìn)程的同步通信

PCB中的信息

  • 進(jìn)程描述信息:包括進(jìn)程標(biāo)識(shí)符(用于標(biāo)志各個(gè)進(jìn)程)和用戶標(biāo)識(shí)符(用于標(biāo)志進(jìn)程歸屬的用戶牌捷,主要為共享和保護(hù)服務(wù));
  • 進(jìn)程控制和管理信息:包括進(jìn)程的狀態(tài)涡驮、進(jìn)程優(yōu)先級等暗甥;
  • 資源分配清單:用于說明有關(guān)內(nèi)存地址空間或虛擬空間的狀況,所打開的文件列表和所使用的輸入/輸出設(shè)備信息捉捅;
  • 處理機(jī)相關(guān)信息:主要是處理機(jī)中各種寄存器的值撤防。

PCB的組織方式

  1. 線性方式:將所有的PCB都組織在一張線性表中,操作系統(tǒng)持有該線性表的首地址棒口;
  2. 鏈接方式:按照進(jìn)程狀態(tài)將PCB分為多個(gè)隊(duì)列寄月,操作系統(tǒng)持有指向各隊(duì)列的指針辜膝;
  3. 索引方式:按照進(jìn)程狀態(tài)的不同建立幾張索引表,操作系統(tǒng)持有指向各個(gè)索引表的指針漾肮。

進(jìn)程控制

進(jìn)程控制一般是由操作系統(tǒng)的內(nèi)核中的原語實(shí)現(xiàn)的厂抖。

操作系統(tǒng)內(nèi)核

現(xiàn)代操作系統(tǒng)一般將OS劃分為若干個(gè)層次,再將OS的不同功能分別設(shè)置在不同層次中初橘。通常將一些與硬件緊密相關(guān)的模塊(如中斷處理程序等)验游、各種設(shè)備的驅(qū)動(dòng)程序以及運(yùn)行頻率較高的模塊(如時(shí)鐘管理、進(jìn)程調(diào)度和許多模塊所公用的一些基本操作)都安排在緊靠硬件的軟件層次中保檐,將它們常駐內(nèi)存耕蝉,這些模塊被稱為內(nèi)核。

通常將處理機(jī)的狀態(tài)分為系統(tǒng)態(tài)用戶態(tài)兩種:

  1. 系統(tǒng)態(tài):又稱為管態(tài)/內(nèi)核態(tài)/核心態(tài)夜只,具有較高的特權(quán)垒在,能執(zhí)行一切指令,訪問所有的寄存器和存儲(chǔ)區(qū)扔亥;
  2. 用戶態(tài):又稱為目態(tài)场躯,具有較低的特權(quán),僅能執(zhí)行規(guī)定的指令旅挤,訪問規(guī)定的寄存器和存儲(chǔ)區(qū)踢关。

一般情況下,應(yīng)用程序運(yùn)行在用戶態(tài)粘茄,操作系統(tǒng)內(nèi)核程序運(yùn)行在系統(tǒng)態(tài)签舞。

不同類型和規(guī)模的OS的內(nèi)核所包含的功能間存在一定的差異,但大多數(shù)OS內(nèi)核都包含支撐功能資源管理功能兩大方面的功能柒瓣。

支撐功能

  1. 中斷處理:中斷處理是內(nèi)核最基本的功能儒搭,各種類型的系統(tǒng)調(diào)用、鍵盤命令的輸入芙贫、進(jìn)程調(diào)度搂鲫、設(shè)備驅(qū)動(dòng)等都依賴于中斷。為減少處理機(jī)中斷的時(shí)間磺平,提高程序執(zhí)行的并發(fā)性魂仍,內(nèi)核在對中斷進(jìn)行“有限處理”后便轉(zhuǎn)入相關(guān)進(jìn)程,由這些進(jìn)程完成后續(xù)處理工作拣挪;
  2. 時(shí)鐘管理:時(shí)鐘管理是內(nèi)核的一項(xiàng)基本功能蓄诽,時(shí)間片輪轉(zhuǎn)調(diào)度、實(shí)時(shí)系統(tǒng)中的截止時(shí)間控制媒吗、批處理系統(tǒng)中的最長運(yùn)行時(shí)間控制等都依賴于時(shí)鐘管理功能仑氛;
  3. 原語操作:原語是由若干條指令組成的,用于完成一定功能的一個(gè)過程,是一個(gè)原子操作(不可分割的基本單位)锯岖。原語在系統(tǒng)態(tài)執(zhí)行介袜,常駐內(nèi)存,在執(zhí)行過程中不允許被中斷出吹。鏈表操作遇伞、進(jìn)程同步、設(shè)備驅(qū)動(dòng)捶牢、CPU切換等功能都可以被定義為原語鸠珠。

資源管理功能

  1. 進(jìn)程管理:進(jìn)程狀態(tài)管理、進(jìn)程調(diào)度與分派秋麸、創(chuàng)建與撤銷PCB等渐排;
  2. 存儲(chǔ)器管理:存儲(chǔ)器空間的分配和回收、內(nèi)存信息保護(hù)灸蟆、代碼對換程序等驯耻;
  3. 設(shè)備管理:緩沖區(qū)管理、設(shè)備的分配和回收等炒考。

進(jìn)程控制

父進(jìn)程與子進(jìn)程

在OS中可缚,允許一個(gè)進(jìn)程創(chuàng)建另一個(gè)進(jìn)程,通常把創(chuàng)建者稱為父進(jìn)程斋枢,被創(chuàng)建者成為子進(jìn)程帘靡。子進(jìn)程可以繼承父進(jìn)程所擁有的資源(如父進(jìn)程打開的文件、分配到的緩沖區(qū)等)瓤帚,當(dāng)子進(jìn)程被撤銷時(shí)描姚,應(yīng)將其從父進(jìn)程那里獲得的資源歸還給父進(jìn)程。在撤銷父進(jìn)程時(shí)缘滥,必須同時(shí)撤銷其所有的子進(jìn)程。

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

引起進(jìn)程創(chuàng)建的典型事件主要有:

  1. 用戶登錄:在分時(shí)系統(tǒng)中谒主,用戶登錄成功后操作系統(tǒng)將為該用戶創(chuàng)建一個(gè)進(jìn)程并插入就緒隊(duì)列中朝扼;
  2. 作業(yè)調(diào)度:在多道批處理系統(tǒng)中,當(dāng)作業(yè)調(diào)度程序按一定的算法調(diào)度到某些作業(yè)時(shí)霎肯,便將它們裝入內(nèi)存擎颖,為它們創(chuàng)建進(jìn)程,并將其插入就緒隊(duì)列观游;
  3. 提供服務(wù):當(dāng)運(yùn)行中的用戶程序提某種請求后(如要求進(jìn)行文件打印等)搂捧,操作系統(tǒng)將專門創(chuàng)建一個(gè)進(jìn)程提供用戶所需要的服務(wù);
  4. 應(yīng)用請求:用戶進(jìn)程自己創(chuàng)建新進(jìn)程懂缕,以便使新進(jìn)程以同創(chuàng)建者進(jìn)程并發(fā)運(yùn)行的方式完成特定任務(wù)允跑。

進(jìn)程的創(chuàng)建過程(創(chuàng)建原語)如下:

  1. 申請空白PCB,為新進(jìn)程創(chuàng)建一個(gè)唯一的進(jìn)程標(biāo)識(shí)號(hào),并從PCB集合中索取一個(gè)空白PCB聋丝;
  2. 為新進(jìn)程分配所需資源索烹,為新進(jìn)程的程序和數(shù)據(jù)及用戶棧分配必要的內(nèi)存空間(在PCB中體現(xiàn))。注意:若資源不足弱睦,則并不是創(chuàng)建失敗而是處于阻塞狀態(tài)百姓,等待所需資源;
  3. 初始化PCB况木,PCB的初始化過程主要包括:初始化標(biāo)識(shí)信息垒拢、初始化處理機(jī)狀態(tài)信息、初始化處理機(jī)控制信息火惊、設(shè)置進(jìn)程的優(yōu)先級等求类;
  4. 如果進(jìn)程就緒隊(duì)列能夠接納新進(jìn)程,便將新進(jìn)程插入就緒隊(duì)列矗晃。

進(jìn)程的終止

引起進(jìn)程終止的事件主要有:

  1. 正常結(jié)束:進(jìn)程的任務(wù)已經(jīng)完成并準(zhǔn)備退出運(yùn)行仑嗅;
  2. 異常結(jié)束:程序在運(yùn)行時(shí)發(fā)生了某種異常,使程序無法繼續(xù)運(yùn)行张症,如存儲(chǔ)區(qū)越界仓技、保護(hù)錯(cuò)、非法指令俗他、特權(quán)指令錯(cuò)脖捻、運(yùn)行超時(shí)、等待超時(shí)兆衅、算術(shù)運(yùn)算錯(cuò)地沮、I/O故障等;
  3. 外界干預(yù):進(jìn)程應(yīng)外界的請求而終止運(yùn)行羡亩,如操作員或操作系統(tǒng)干預(yù)摩疑、父進(jìn)程請求、父進(jìn)程終止等畏铆。

進(jìn)程的終止過程(撤銷原語)如下:

  1. 根據(jù)被終止的進(jìn)程標(biāo)識(shí)符雷袋,從PCB集合中檢索出該進(jìn)程的PCB,從中讀出該進(jìn)程的狀態(tài)辞居;
  2. 若被終止的進(jìn)程正處于執(zhí)行狀態(tài)則立即終止該進(jìn)程的執(zhí)行楷怒,并置調(diào)度標(biāo)志為真,用于指示該進(jìn)程被終止后重新進(jìn)行進(jìn)程調(diào)度瓦灶;
  3. 若該進(jìn)程還有子孫進(jìn)程則將其所有子孫進(jìn)程全部終止鸠删,以防它們成為不可控的進(jìn)程;
  4. 將被終止的進(jìn)程所擁有的全部資源歸還給其父進(jìn)程或者歸還給系統(tǒng)贼陶;
  5. 將被終止的進(jìn)程的PCB從所在隊(duì)列或鏈表中移出刃泡,等待其他程序來搜集信息巧娱。

進(jìn)程的阻塞與喚醒

引起進(jìn)程阻塞的原因:

  1. 申請共享資源失敗:進(jìn)程向系統(tǒng)申請資源時(shí),由于系統(tǒng)沒有足夠的資源分配給它而轉(zhuǎn)變?yōu)樽枞麪顟B(tài)捅僵;
  2. 等待某種操作的完成:當(dāng)進(jìn)程啟動(dòng)了某種操作后家卖,若該進(jìn)程必須在操作完成之后才能繼續(xù)執(zhí)行,則該進(jìn)程變?yōu)樽枞麪顟B(tài)等待操作完成庙楚;
  3. 新數(shù)據(jù)尚未到達(dá):對于相互合作的進(jìn)程上荡,如果一個(gè)進(jìn)程需要先獲得另一進(jìn)程提供的數(shù)據(jù)才能繼續(xù)執(zhí)行,如果所需數(shù)據(jù)尚未到達(dá)馒闷,進(jìn)程就處于阻塞狀態(tài)酪捡;
  4. 等待新任務(wù)的到達(dá):在某些系統(tǒng)中(特別是網(wǎng)絡(luò)環(huán)境下的OS),往往設(shè)置一些特定的系統(tǒng)進(jìn)程纳账,每當(dāng)它們完成任務(wù)后就變?yōu)樽枞麪顟B(tài)等待新任務(wù)的到來逛薇。

正在執(zhí)行的進(jìn)程如果發(fā)生了上述事件,進(jìn)程便通過調(diào)用阻塞原語block將自己阻塞疏虫,由此可見阻塞是進(jìn)程的一種主動(dòng)行為永罚。

進(jìn)程的阻塞過程(阻塞原語block)如下:

  1. 找到將要被阻塞的進(jìn)程的標(biāo)識(shí)號(hào)所對應(yīng)的PCB;
  2. 若該進(jìn)程處于運(yùn)行態(tài)卧秘,則保留其處理機(jī)狀態(tài)呢袱,將其運(yùn)行狀態(tài)改為阻塞態(tài)并停止運(yùn)行;
  3. 把該P(yáng)CB插入相應(yīng)事件的阻塞隊(duì)列翅敌,將處理機(jī)資源調(diào)度給其他就緒進(jìn)程并進(jìn)行切換羞福;

當(dāng)被阻塞進(jìn)程所期待的事件出現(xiàn)時(shí),則由有關(guān)進(jìn)程調(diào)用喚醒原語wakeup將等待該事件的進(jìn)程喚醒蚯涮。

進(jìn)程的喚醒過程(喚醒原語wakeup)如下:

  1. 在該事件的阻塞隊(duì)列中找到相應(yīng)進(jìn)程的PCB治专;
  2. 把該P(yáng)CB從阻塞隊(duì)列中移出,將其狀態(tài)設(shè)置為就緒態(tài)遭顶;
  3. 把該P(yáng)CB插入就緒隊(duì)列中张峰。

注意:block原語和wakeup原語是一對作用剛好相反的原語,必須成對使用棒旗;block原語是由被阻塞進(jìn)程自我調(diào)用實(shí)現(xiàn)的喘批,而wakeup原語則是由一個(gè)與被喚醒進(jìn)程合作或其他相關(guān)進(jìn)程的調(diào)用實(shí)現(xiàn)的。

進(jìn)程的掛起與激活

進(jìn)程的掛起過程(掛起原語suspend)如下:

  1. 檢查被掛起進(jìn)程的狀態(tài)嗦哆,若處于活動(dòng)狀態(tài)則置為靜止就緒態(tài)谤祖,若處于阻塞態(tài)則置為靜止阻塞態(tài)婿滓;
  2. 把該進(jìn)程的PCB復(fù)制到某指定的內(nèi)存區(qū)域老速,方便用戶或父進(jìn)程考查該進(jìn)程的運(yùn)行情況;
  3. 若被掛起的進(jìn)程正在執(zhí)行則重新進(jìn)行進(jìn)程調(diào)度凸主。

進(jìn)程的激活過程(激活原語active)如下:

  1. 將被激活的進(jìn)程從外存調(diào)入內(nèi)存橘券,檢查該進(jìn)程的狀態(tài),若為靜止就緒態(tài)則改為活動(dòng)就緒態(tài),若為靜止阻塞態(tài)則改為活動(dòng)阻塞態(tài)旁舰;
  2. 若采用搶占調(diào)度策略锋华,則根據(jù)被激活的進(jìn)程的優(yōu)先級檢查是否要重新進(jìn)行進(jìn)程調(diào)度;
  3. 若優(yōu)先級低則不重新調(diào)度箭窜,否則將處理機(jī)分配給被激活的進(jìn)程毯焕。

進(jìn)程切換

進(jìn)程切換指的是處理機(jī)從一個(gè)進(jìn)程的運(yùn)行轉(zhuǎn)到另一個(gè)進(jìn)程上運(yùn)行,在這個(gè)過程中磺樱,進(jìn)程的運(yùn)行環(huán)境產(chǎn)生了實(shí)質(zhì)性的變化纳猫。

進(jìn)程切換的過程如下:

  1. 保存處理機(jī)上下文,包括程序計(jì)數(shù)器PC和其他寄存器竹捉;
  2. 更新PCB信息芜辕;
  3. 把進(jìn)程的PCB移入相應(yīng)的隊(duì)列,如就緒隊(duì)列和某事件的阻塞隊(duì)列块差;
  4. 選擇另一個(gè)進(jìn)程執(zhí)行侵续,并更新其PCB;
  5. 更新內(nèi)存管理的數(shù)據(jù)結(jié)構(gòu)憨闰;
  6. 恢復(fù)處理機(jī)的上下文状蜗。

注意1:進(jìn)程切換與處理機(jī)模式切換(用戶態(tài)->內(nèi)核態(tài))不同,模式切換時(shí)處理機(jī)邏輯上可能還在統(tǒng)一進(jìn)程中運(yùn)行起趾。若進(jìn)程因中斷或異常而進(jìn)入核心態(tài)運(yùn)行诗舰,執(zhí)行完后又回到用戶態(tài)剛剛被中斷的程序運(yùn)行,則OS只需要恢復(fù)進(jìn)程進(jìn)入內(nèi)核時(shí)所保存的CPU現(xiàn)場训裆,而無需改變當(dāng)前進(jìn)程的環(huán)境信息眶根;若要切換進(jìn)程,當(dāng)前正在運(yùn)行的進(jìn)程發(fā)生了改變边琉,則當(dāng)前進(jìn)程的環(huán)境信息也需要改變属百。

注意2:進(jìn)程調(diào)度是決定處理機(jī)資源分配給哪個(gè)進(jìn)程的行為,是一種決策行為变姨;進(jìn)程切換是指世紀(jì)分配處理機(jī)的行為族扰,是一種執(zhí)行行為。一般來說定欧,先有資源的調(diào)度后有進(jìn)程切換渔呵。

進(jìn)程同步

進(jìn)程同步的基本概念

進(jìn)程同步機(jī)制的主要任務(wù),是對多個(gè)相關(guān)進(jìn)程在執(zhí)行次序上進(jìn)行協(xié)調(diào)砍鸠,使并發(fā)執(zhí)行的諸進(jìn)程之間能按照一定的規(guī)則(或時(shí)序)共享系統(tǒng)資源扩氢,并能很好地相互合作,從而使程序的執(zhí)行具有可再現(xiàn)性爷辱。

兩種形式的制約關(guān)系

  1. 直接相互制約關(guān)系:又稱同步录豺,是指為了完成某種任務(wù)而建立的兩個(gè)或多個(gè)進(jìn)程朦肘,這些進(jìn)程因?yàn)樾枰谀承┪恢蒙蠀f(xié)調(diào)它們的工作次序而等待、傳遞信息所產(chǎn)生的制約關(guān)系双饥。進(jìn)程間的直接制約關(guān)系來源于它們的相互合作媒抠;
  2. 間接相互制約關(guān)系:又稱互斥,當(dāng)一個(gè)進(jìn)程進(jìn)入臨界區(qū)訪問資源時(shí)咏花,另一個(gè)進(jìn)程必須等待趴生;當(dāng)占用臨界資源的進(jìn)程退出臨界區(qū)后,另一進(jìn)程才允許訪問此臨界資源昏翰。

在多道程序環(huán)境下冲秽,由于存在上述兩種相互制約的關(guān)系,進(jìn)程在運(yùn)行的過程中是否能獲得處理機(jī)運(yùn)行與以怎樣的速度運(yùn)行并不能由進(jìn)程自身所控制矩父,此即進(jìn)程的異步性锉桑。由此會(huì)產(chǎn)生對共享變量或數(shù)據(jù)結(jié)構(gòu)的不正確訪問次序,從而造成進(jìn)程每次執(zhí)行的結(jié)果不一致窍株。這種差錯(cuò)往往與時(shí)間有關(guān)民轴,故稱“與時(shí)間有關(guān)的錯(cuò)誤”。為了杜絕這種差錯(cuò)球订,必須對進(jìn)程的執(zhí)行次序進(jìn)行協(xié)調(diào)后裸,保證進(jìn)程能按順序執(zhí)行。

臨界資源

雖然多個(gè)進(jìn)程可以共享系統(tǒng)中的各種資源冒滩,但是許多硬件資源如打印機(jī)微驶、磁帶機(jī)等都屬于臨界資源;此外开睡,還有許多變量、數(shù)據(jù)等都可以被若干進(jìn)程共享篇恒,它們也屬于臨界資源胁艰。諸進(jìn)程之間應(yīng)采取互斥方式實(shí)現(xiàn)對這種資源的共享款筑。

臨界區(qū)

不論是硬件臨界資源還是軟件臨界資源,多個(gè)進(jìn)程必須互斥地對它們進(jìn)行訪問腾么,每個(gè)進(jìn)程中訪問臨界資源的那段代碼稱為臨界區(qū)奈梳。

為了保證臨界資源的正確使用,可以把臨界資源的訪問分為四個(gè)部分:

  1. 進(jìn)入?yún)^(qū):為了進(jìn)入臨界區(qū)使用臨界資源解虱,在進(jìn)入?yún)^(qū)要檢查可否進(jìn)入臨界區(qū)攘须,若能進(jìn)入臨界區(qū),則應(yīng)設(shè)置正在訪問臨界區(qū)的標(biāo)志饭寺,以阻止其他進(jìn)程同時(shí)進(jìn)入臨界區(qū)阻课;
  2. 臨界區(qū):進(jìn)程中訪問臨界資源的代碼,又稱臨界段艰匙;
  3. 退出區(qū):將正在訪問臨界區(qū)的標(biāo)志清除限煞;
  4. 剩余區(qū):代碼中的其余部分。

偽代碼:

do {
    entry section;          // 進(jìn)入?yún)^(qū)
    critical section;       // 臨界區(qū)
    exit section;           // 退出區(qū)
    remainder section;      // 剩余區(qū)
} while (true)

同步機(jī)制應(yīng)遵循的規(guī)則

所有同步機(jī)制都應(yīng)遵循以下四種原則:

  1. 空閑讓進(jìn):當(dāng)無進(jìn)程處于臨界區(qū)時(shí)员凝,表明臨界資源處于空閑狀態(tài)署驻,應(yīng)允許一個(gè)請求進(jìn)入臨界區(qū)的進(jìn)程立即進(jìn)入自己的臨界區(qū),以有效地利用臨界資源健霹;
  2. 忙則等待:當(dāng)有進(jìn)程已進(jìn)入臨界區(qū)時(shí)糖埋,表明臨界資源正在被訪問征候,其它試圖進(jìn)入臨界區(qū)的進(jìn)程必須等待,以保證對臨界資源的互斥訪問跑揉;
  3. 有限等待:對要求訪問臨界區(qū)的進(jìn)程,應(yīng)保證在有限時(shí)間內(nèi)能進(jìn)入自己的臨界區(qū),以避免陷入“死等”狀態(tài)甜无;
  4. 讓權(quán)等待:當(dāng)進(jìn)程不能進(jìn)入自己的臨界區(qū)時(shí),應(yīng)立即釋放處理機(jī),以避免進(jìn)程陷入“忙等”狀態(tài)寨蹋。

軟件實(shí)現(xiàn)方法

單標(biāo)志法

基本思想:設(shè)置一個(gè)公用整型變量turn秸苗,用于指示被允許進(jìn)入臨界區(qū)的進(jìn)程編號(hào)。

偽代碼:

進(jìn)程P0:

while (turn != 0);      // 進(jìn)入?yún)^(qū)
critical section;       // 臨界區(qū)
turn = 1;               // 退出區(qū)
remainder section;      // 剩余區(qū)

進(jìn)程P1:

while (turn != 1);      // 進(jìn)入?yún)^(qū)
critical section;       // 臨界區(qū)
turn = 0;               // 退出區(qū)
remainder section;      // 剩余區(qū)
  • 優(yōu)點(diǎn):可以保證每次只有一個(gè)進(jìn)程進(jìn)入臨界區(qū);
  • 缺點(diǎn):兩個(gè)進(jìn)程必須交替進(jìn)入臨界區(qū)弧可;若某個(gè)進(jìn)程不再進(jìn)入臨界區(qū)氧秘,則另一個(gè)進(jìn)程也將無法進(jìn)入臨界區(qū)(違背“空閑讓進(jìn)”)搔确,容易造成資源利用不充分。

例如,若P0進(jìn)入臨界區(qū)并順利離開机隙,而P1不進(jìn)入臨界區(qū),turn = 1就會(huì)一直成立葱跋,P0就無法再次進(jìn)入臨界區(qū)。

雙標(biāo)志法先檢查

基本思想:在進(jìn)程進(jìn)入臨界區(qū)之前先檢查臨界資源是否正在被訪問模庐,如果是验庙,則該進(jìn)程需等待;否則,該進(jìn)程就可以進(jìn)入自己的臨界區(qū)藤巢。設(shè)置一個(gè)數(shù)據(jù)flag[i],第i個(gè)元素為FALSE表示Pi進(jìn)程沒有進(jìn)入臨界區(qū)绍刮,否則表示Pi進(jìn)程進(jìn)入臨界區(qū)得运。

偽代碼:

進(jìn)程Pi:

while (flag[j]);        // (1)進(jìn)入?yún)^(qū)彬檀,此時(shí)flag[i] = FALSE
flag[i] = TRUE;         // (3)進(jìn)入?yún)^(qū)
critical section;       // 臨界區(qū)
flag[i] = FALSE;        // 退出區(qū)
remainder section;      // 剩余區(qū)

進(jìn)程Pj:

while (flag[i]);        // (2)進(jìn)入?yún)^(qū)诽偷,此時(shí)flag[j] = FALSE
flag[j] = TRUE;         // (4)進(jìn)入?yún)^(qū)
critical section;       // 臨界區(qū)
flag[j] = FALSE;        // 退出區(qū)
remainder section;      // 剩余區(qū)
  • 優(yōu)點(diǎn):進(jìn)程不需要交替進(jìn)入臨界區(qū)深浮,可連續(xù)使用菌瘫;
  • 缺點(diǎn):Pi和Pj可能同時(shí)進(jìn)入臨界區(qū)忿等,若按(1)->(2)->(3)->(4)執(zhí)行時(shí)二者就會(huì)同時(shí)進(jìn)入臨界區(qū)(違背“忙則等待”)庵寞。

雙標(biāo)志法后檢查

基本思想:在“雙標(biāo)志法先檢查”的基礎(chǔ)上逸尖,進(jìn)程先將自己的標(biāo)志設(shè)置為TRUE渐白,再檢測對方的狀態(tài)標(biāo)志,若對方的標(biāo)志為TRUE則等待,否則進(jìn)入臨界區(qū)奕剃。

偽代碼:

進(jìn)程Pi:

flag[i] = TRUE;         // (1)進(jìn)入?yún)^(qū)
while (flag[j]);        // 進(jìn)入?yún)^(qū)
critical section;       // 臨界區(qū)
flag[i] = FALSE;        // 退出區(qū)
remainder section;      // 剩余區(qū)

進(jìn)程Pj:

flag[j] = TRUE;         // (2)進(jìn)入?yún)^(qū)
while (flag[i]);        // 進(jìn)入?yún)^(qū)
critical section;       // 臨界區(qū)
flag[j] = FALSE;        // 退出區(qū)
remainder section;      // 剩余區(qū)
  • 優(yōu)點(diǎn):避免了“雙標(biāo)志法先檢查”同時(shí)進(jìn)入臨界區(qū)的問題肺然;
  • 缺點(diǎn):若(1)和(2)幾乎同時(shí)執(zhí)行時(shí)悍缠,兩進(jìn)程的標(biāo)志都被置為TRUE滤港,雙方檢測對方狀態(tài)(執(zhí)行while語句)時(shí)都無法進(jìn)入臨界區(qū),兩進(jìn)程無限期等待,造成“饑餓”現(xiàn)象缝龄;

Peterson's Algorithm

基本思想:在“雙標(biāo)志法后檢查”的基礎(chǔ)上重新設(shè)置變量turn瞎饲,每個(gè)進(jìn)程設(shè)置自己的標(biāo)志后再設(shè)置turn標(biāo)志妄田,然后同時(shí)檢測另一個(gè)進(jìn)程的狀態(tài)標(biāo)志和turn標(biāo)志,以保證只能有一個(gè)進(jìn)程進(jìn)入臨界區(qū)。

偽代碼:

進(jìn)程Pi:

flag[i] = TRUE; turn = j;       // 進(jìn)入?yún)^(qū)
while (flag[j] && turn == j);   // 進(jìn)入?yún)^(qū)
critical section;               // 臨界區(qū)
flag[i] = FALSE;                // 退出區(qū)
remainder section;              // 剩余區(qū)

進(jìn)程Pj:

flag[j] = TRUE; turn = i;       // 進(jìn)入?yún)^(qū)
while (flag[i] && turn == i);   // 進(jìn)入?yún)^(qū)
critical section;               // 臨界區(qū)
flag[j] = FALSE;                // 退出區(qū)
remainder section;              // 剩余區(qū)
  • 優(yōu)點(diǎn):解決了“饑餓”問題。

硬件同步機(jī)制

通過硬件支持實(shí)現(xiàn)臨界段問題的方法稱為低級方法薯演,或稱元方法

中斷屏蔽方法

因?yàn)镃PU只在發(fā)生中斷時(shí)引起進(jìn)程切換愉镰,所以關(guān)中斷能保證當(dāng)前運(yùn)行的進(jìn)程讓臨界區(qū)的代碼順利地執(zhí)行完。其典型模式為:

關(guān)中斷
臨界區(qū)
開中斷

這種方法降低了處理機(jī)交替執(zhí)行程序的能力,因此執(zhí)行的效率會(huì)明顯降低讼渊。對內(nèi)核來說,在它執(zhí)行更新變量或列表的幾條指令時(shí)關(guān)中斷是很方便的,但是將關(guān)中斷的權(quán)利交給用戶則很不明智奶甘。

硬件指令方法

依靠TestAndSetSwap兩條由硬件直接實(shí)現(xiàn)的、不會(huì)被中斷的指令完成钉赁。

TestAndSet指令的功能描述如下:

boolean TestAndSet(boolean *lock) {
    boolean old;
    old = *lock;
    *lock = true;
    return old;
}

可以為每個(gè)臨界資源設(shè)置一個(gè)共享布爾變量lock邑蒋,初值為false,該變量的值為true表示資源正在被占用束莫。在進(jìn)程訪問臨界資源前策严,利用TestAndSet指令檢查和修改標(biāo)志lock。偽代碼如下:

while (TestAndSet(&lock));
critical section;
lock = false;
remainder section;

Swap指令的功能描述如下:

Swap(boolean *a, boolean *b) {
    boolean temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

該指令的功能是交換兩個(gè)字(字節(jié))的內(nèi)容倔韭。

應(yīng)為每個(gè)臨界資源設(shè)置一個(gè)共享布爾變量lock,初值為false醇疼,在每個(gè)進(jìn)程中再設(shè)置一個(gè)局部變量key壶栋,初值為true,用于與lock交換信息毙玻。在進(jìn)入臨界區(qū)前,先利用Swap指令交換lockkey的內(nèi)容运准,然后檢查key的狀態(tài)米者,有進(jìn)程在臨界區(qū)時(shí)胰丁,重復(fù)檢查和交換過程机蔗,直到進(jìn)程退出幔嗦。偽代碼如下:

key = true;
while (key != false) {
    Swap(&lock, &key);
}
critical section;
lock = false;
remainder section;

硬件同步機(jī)制的優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):
  • 不管是單處理機(jī)還是多處理機(jī)嬉挡,都適用于任意數(shù)目的進(jìn)程因谎;
  • 簡單风皿、容易驗(yàn)證其正確性;
  • 可以支持進(jìn)程內(nèi)有多個(gè)臨界區(qū)魔眨,只需為每個(gè)臨界區(qū)設(shè)置一個(gè)布爾變量。
  • 缺點(diǎn):
  • 進(jìn)程等待進(jìn)入臨界區(qū)時(shí)要耗費(fèi)處理機(jī)時(shí)間,不能實(shí)現(xiàn)讓權(quán)等待侥啤;
  • 由于是從等待進(jìn)程中隨機(jī)選擇一個(gè)進(jìn)入臨界區(qū),有的進(jìn)程可能一直得不到調(diào)度醉箕,從而導(dǎo)致“饑餓”現(xiàn)象姻报;

信號(hào)量機(jī)制

信號(hào)量機(jī)制是一種功能較強(qiáng)的機(jī)制,可用來解決互斥與同步問題治拿,它只能被兩個(gè)標(biāo)準(zhǔn)的原語wait(S)signal(S)訪問嚷掠,也可記為P操作V操作未檩。

原語是指完成某種功能且不可被分割孙蒙、不能被中斷的執(zhí)行序列,可由硬件實(shí)現(xiàn)透典,在單處理機(jī)上可通過軟件屏蔽中斷的方法實(shí)現(xiàn)凑队。

整型信號(hào)量

整型信號(hào)量被定義為一個(gè)表示資源數(shù)目的整型量S西壮,waitsignal操作如下:

wait (S) {
    while (S <= 0);
    S -= 1;
}

signal (S) {
    S += 1;
}

wait操作中霍狰,只要信號(hào)量S <= 0可都,就會(huì)不斷測試(while循環(huán))。因此蚓耽,該機(jī)制未遵循“讓權(quán)等待”而是使進(jìn)程處于“忙等”狀態(tài)渠牲。

記錄型信號(hào)量

記錄型信號(hào)量除了需要一個(gè)用于代表資源數(shù)目的整型變量value外,還需要再增加一個(gè)進(jìn)程鏈表L谚咬,用于鏈接所有等待該資源的進(jìn)程辑鲤。

記錄型信號(hào)量可描述為:

typedef struct {
    int value;
    struct process *L;
} semaphore;

相應(yīng)的wait礁击、signal操作如下:

void wait(semaphore S) {    // 相當(dāng)于申請資源
    S.value--;
    if (S.value < 0) {
        add this process to S.L;
        block(S.L);
    }
}
void signal(semaphore S) {
    S.value++;
    if (S.value <= 0) {
        remove a process P from S.L;
        wakeup(P);
    }
}

wait操作:S.value--表示進(jìn)程請求該類資源漩勤,當(dāng)S.value < 0時(shí)表示該類資源已經(jīng)分配完畢,此時(shí)進(jìn)程調(diào)用block原語進(jìn)行自我阻塞酬滤,放棄處理機(jī)译打,并加入該類資源的等待隊(duì)列L搪缨。因此奏篙,該機(jī)制遵循了“讓權(quán)等待”原則炸茧。

signal操作:進(jìn)程釋放了一個(gè)資源,S.value++表示系統(tǒng)中可供分配的資源數(shù)量加1形导,若加1后仍然是S.value <= 0锰霜,則表示S.L中還有等待該資源的進(jìn)程被阻塞焚刺,因此還應(yīng)調(diào)用wakeup原語浅役,將S.L中一個(gè)等待該資源的進(jìn)程喚醒。

可以理解為P操作是獲取鎖衅斩,V操作是釋放鎖蒜田。

利用信號(hào)量實(shí)現(xiàn)進(jìn)程同步

設(shè)P2中的語句y需要使用進(jìn)程P1中的語句x的運(yùn)行結(jié)果(即語句y必須在語句x之后執(zhí)行)隆豹,利用信號(hào)量實(shí)現(xiàn)進(jìn)程同步的算法如下:

semaphore S = 0;    // 初始化信號(hào)量

P1() {
    ...
    x;              // 語句x
    V(S);           // 釋放鎖(告訴進(jìn)程P2府寒,x語句已完成)
    ...
}

P2() {
    ...
    P(S);           // 獲取鎖(檢查語句x是否運(yùn)行完成)
    y;              // 語句y
    ...
}

總結(jié):前V后P

利用信號(hào)量實(shí)現(xiàn)進(jìn)程互斥

只需要把臨界區(qū)置于P(S)和V(S)之間,就可以實(shí)現(xiàn)兩個(gè)進(jìn)程對資源的互斥訪問。算法如下:

semaphore S = 1;        // 初始化信號(hào)量

P1() {
    ...
    P(S);               // 準(zhǔn)備開始訪問臨界資源,加鎖
    進(jìn)程P1的臨界區(qū);
    V(S);               // 訪問結(jié)束初嘹,解鎖
    ...
}

P2() {
    ...
    P(S);               // 加鎖
    進(jìn)程P2的臨界區(qū);
    V(S);               // 解鎖
    ...
}

總結(jié):若某個(gè)行為要用到某種資源窃躲,要先對這種資源執(zhí)行P操作褐桌;若某個(gè)行為會(huì)提供某種資源,需要先對這種資源執(zhí)行V操作延赌,即在臨界區(qū)前后分別P、V

利用信號(hào)量實(shí)現(xiàn)前趨關(guān)系

設(shè)有如下前趨圖:

前趨圖

其中S1叉橱,S2挫以,...,S6都是最簡單的程序段(只有一條語句)窃祝。為使各個(gè)程序段能正確執(zhí)行掐松,應(yīng)設(shè)置若干個(gè)初始值為“0”的信號(hào)量。如為保證S1 -> S2, S1 -> S3的前趨關(guān)系粪小,應(yīng)分別設(shè)置信號(hào)量a大磺、b;同樣探膊,為保證S2 -> S4, S2 -> S5, S3 -> S6, S4 -> S6, S5 -> S6的前趨關(guān)系杠愧,應(yīng)設(shè)置信號(hào)量c、d逞壁、e流济、f锐锣、g。算法如下:

p1() {
    S1;
    signal(a);
    signal(b);
}

p2() {
    wait(a);
    S2;
    signal(c);
    signal(d);
}

p3() {
    wait(b);
    S3;
    signal(e);
}

p4() {
    wait(c);
    S4;
    signal(f);
}

p5() {
    wait(d);
    S5;
    signal(g);
}

p6() {
    wait(e);
    wait(f);
    wait(g);
    S6;
}

main() {
    semaphore a, b, c, d, e, f, g;
    a.value = b.value = c.value = 0;
    d.value = e.value = 0;
    f.value = g.value = 0;
    
    cobegin
        p1();
        p2();
        p3();
        p4();
        p5();
        p6();
    coend
}

管程

定義

系統(tǒng)中的各種硬件資源和軟件資源均可利用數(shù)據(jù)結(jié)構(gòu)抽象地描述其資源特性绳瘟,即用少量信息和對該資源所執(zhí)行的操作來表征該資源刺下,而忽略它們的內(nèi)部結(jié)構(gòu)和實(shí)現(xiàn)細(xì)節(jié)。因此稽荧,可以利用共享數(shù)據(jù)結(jié)構(gòu)抽象地表示系統(tǒng)中的共享資源橘茉,并且將對該共享數(shù)據(jù)結(jié)構(gòu)實(shí)施的特定操作定義為一組過程(函數(shù)),進(jìn)程對共享資源的申請姨丈、釋放和其它操作必須通過這組過程間接地對共享數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)操作畅卓。代表共享資源的數(shù)據(jù)結(jié)構(gòu)及由對該共享數(shù)據(jù)結(jié)構(gòu)實(shí)施操作的一組過程所組成的資源管理程序共同構(gòu)成了一個(gè)操作系統(tǒng)的資源管理模塊,稱為管程蟋恬。管程定義了一個(gè)數(shù)據(jù)結(jié)構(gòu)和能為并發(fā)進(jìn)程所執(zhí)行(在該數(shù)據(jù)結(jié)構(gòu)上)的一組操作翁潘,這組操作能同步進(jìn)程改變管程中的數(shù)據(jù)。

管程由四部分組成:

  1. 管程的名稱
  2. 局部于管程內(nèi)部的共享數(shù)據(jù)結(jié)構(gòu)說明歼争;
  3. 對該數(shù)據(jù)結(jié)構(gòu)進(jìn)行操作的一組過程(或函數(shù))拜马;
  4. 對局部于管程的共享數(shù)據(jù)結(jié)構(gòu)設(shè)置初值的語句。

管程的定義描述舉例如下:

monitor Demo {          // 定義一個(gè)名稱為“Demo”的管程
    // 定義共享數(shù)據(jù)結(jié)構(gòu)沐绒,對應(yīng)系統(tǒng)中的某些共享資源
    共享數(shù)據(jù)結(jié)構(gòu)S;
    
    // 對共享數(shù)據(jù)結(jié)構(gòu)的初始化的語句
    init_code() {
        S = 5;          // 初始資源數(shù)等于5
    }
    
    // 過程1: 申請一個(gè)資源
    take_away() {
        對共享數(shù)據(jù)結(jié)構(gòu)S的一系列處理俩莽;
        S--;            // 可用資源數(shù)-1
        ...
    }
    
    // 過程2: 歸還一個(gè)資源
    give_back() {
        對共享數(shù)據(jù)結(jié)構(gòu)S的一系列處理;
        S++;            // 可用資源數(shù)+1
        ...
    }
}

實(shí)際上乔遮,管程包含了面向?qū)ο蟮乃枷耄?/p>

  • 管程把對共享資源的操作封裝起來扮超,管程內(nèi)部的共享數(shù)據(jù)結(jié)構(gòu)只能被管程的過程所訪問,一個(gè)進(jìn)程只有通過調(diào)用管程內(nèi)的過程才能進(jìn)入管程訪問共享資源蹋肮;
  • 每次僅允許一個(gè)進(jìn)程進(jìn)入管程出刷,從而實(shí)現(xiàn)進(jìn)程互斥(由編譯器實(shí)現(xiàn))。

從語言的角度來看坯辩,管程主要有以下特征:

  1. 模塊化:管程是一個(gè)基本的程序單位馁龟,可單獨(dú)編譯;
  2. 抽象數(shù)據(jù)類型:管程中不僅有數(shù)據(jù)漆魔,還有對數(shù)據(jù)的操作坷檩;
  3. 信息掩蔽:管程中的數(shù)據(jù)結(jié)構(gòu)只能被管程中的過程訪問,這些過程也是在管程內(nèi)部定義的有送,供管程外的進(jìn)程調(diào)用淌喻,而管程中的數(shù)據(jù)結(jié)構(gòu)和過程(函數(shù))的具體實(shí)現(xiàn)外部不可見。

管程和進(jìn)程的不同:

  1. 雖然二者都定義了數(shù)據(jù)結(jié)構(gòu)雀摘,但進(jìn)程定義是私有數(shù)據(jù)結(jié)構(gòu)PCB裸删,管程定義的是公共數(shù)據(jù)結(jié)構(gòu),如消息隊(duì)列等阵赠;
  2. 二者都存在對各自數(shù)據(jù)結(jié)構(gòu)上的操作涯塔,但進(jìn)程是由順序程序執(zhí)行的有關(guān)操作肌稻,而管程主要是進(jìn)行同步操作和初始化操作;
  3. 設(shè)置進(jìn)程的目的在于實(shí)現(xiàn)系統(tǒng)的并發(fā)性匕荸,設(shè)置管程的目的是解決共享資源的互斥使用問題爹谭;
  4. 進(jìn)程通過調(diào)用管程中的過程對共享數(shù)據(jù)結(jié)構(gòu)實(shí)行操作,該過程就如通常的子程序一樣被調(diào)用榛搔,因而管程為被動(dòng)工作方式诺凡,進(jìn)程為主動(dòng)工作方式;
  5. 進(jìn)程間能并發(fā)執(zhí)行践惑,而管程則不能與其調(diào)用者并發(fā)腹泌;
  6. 進(jìn)程具有動(dòng)態(tài)性,管程則是操作系統(tǒng)中的一個(gè)資源管理模塊尔觉,供進(jìn)程調(diào)用凉袱。

條件變量

當(dāng)一個(gè)進(jìn)程調(diào)用了管程,在管程中被阻塞或掛起侦铜,直到阻塞或掛起的原因解除专甩。而在此期間,如果該進(jìn)程不釋放管程钉稍,則其他進(jìn)程無法進(jìn)入管程涤躲,被迫長時(shí)間等待。為了解決這個(gè)問題嫁盲,引入了條件變量condition篓叶。通常,一個(gè)進(jìn)程被阻塞或掛起的條件(原因)可有多個(gè)羞秤,因此在管程中設(shè)置了多個(gè)條件變量,對這些條件變量的訪問只能在管程中進(jìn)行左敌。

管程中對每個(gè)條件變量都必須予以說明瘾蛋,其形式為:condition x, y;對條件變量的操作僅僅是waitsignal,因此條件變量也是一種抽象數(shù)據(jù)類型矫限,每個(gè)條件變量保存了一個(gè)鏈表哺哼,用于記錄因該條件變量而阻塞的所有進(jìn)程,同時(shí)提供的兩個(gè)操作可以表示為x.waitx.signal叼风。其含義為:

  • x.wait:正在調(diào)用管程的進(jìn)程因x條件需要被阻塞或掛起取董,則調(diào)用x.wait將自己插入到x條件的等待隊(duì)列上,并釋放管程无宿,直到x條件變化茵汰。此時(shí)其他進(jìn)程可以使用該管程。
  • x.signal:正在調(diào)用管程的進(jìn)程發(fā)現(xiàn)x條件發(fā)生了變化孽鸡,則調(diào)用x.signal重新啟動(dòng)一個(gè)因x條件而被阻塞或掛起的進(jìn)程蹂午,如果存在多個(gè)這樣的進(jìn)程栏豺,則選擇其中的一個(gè),如果沒有豆胸,繼續(xù)執(zhí)行原進(jìn)程奥洼,而不產(chǎn)生任何結(jié)果。

條件變量的定義和使用如下:

monitor Demo {
    共享數(shù)據(jù)結(jié)構(gòu)S;
    condition x;        // 定義一個(gè)條件變量x
    
    init_code() {
        ...
    }
    
    take_away() {
        if (S <= 0) {
            x.wait();   // 資源不夠晚胡,在條件變量x上阻塞等待
        }
        資源足夠灵奖,分配資源,做一系列相應(yīng)處理估盘;
    }
    
    give_back() {
        歸還資源瓷患,做一系列相應(yīng)處理;
        if (有進(jìn)程在等待) {
            x.signal(); // 喚醒一個(gè)阻塞進(jìn)程
        }
    }
}

條件變量與信號(hào)量的比較:

  • 相似點(diǎn):條件變量的wait/signal操作類似于信號(hào)量的P/V操作忿檩,可以實(shí)現(xiàn)進(jìn)程的阻塞/喚醒尉尾;
  • 不同點(diǎn):條件變量是“沒有值”的,僅實(shí)現(xiàn)了“排隊(duì)等待”功能燥透;信號(hào)量是“有值”的沙咏,信號(hào)量的值反映了剩余資源數(shù),而在管程中班套,剩余資源數(shù)用共享數(shù)據(jù)結(jié)構(gòu)記錄肢藐。

經(jīng)典進(jìn)程的同步問題

進(jìn)程同步PV操作題分析步驟:

  1. 關(guān)系分析:找出題目中各個(gè)進(jìn)程,分析它們之間同步吱韭、互斥的關(guān)系吆豹;
  2. 整理思路:根據(jù)各進(jìn)程的操作流程確定P、V操作的大致順序理盆;
  3. 信號(hào)量設(shè)置:設(shè)置需要的信號(hào)量痘煤,并根據(jù)題目確定信號(hào)量初值(互斥信號(hào)量初值一般為1,同步信號(hào)量初值要看系統(tǒng)中資源初始數(shù)目多少)猿规。

生產(chǎn)者-消費(fèi)者問題

問題描述

系統(tǒng)中有一組生產(chǎn)者進(jìn)程和一組消費(fèi)者進(jìn)程共享一個(gè)公用緩沖池衷快,緩沖池中具有n個(gè)緩沖區(qū),只有緩沖池沒滿的時(shí)候姨俩,生產(chǎn)者進(jìn)程才能把消息放入緩沖區(qū)蘸拔,否則必須等待;只有緩沖池不空時(shí)环葵,消費(fèi)者才能從中取出消息调窍,否則必須等待。由于緩沖池是臨界資源张遭,它只允許一個(gè)生產(chǎn)者放入消息或一個(gè)消費(fèi)者從中取出消息邓萨。

代碼

semaphore mutex = 1;        // 互斥信號(hào)量,實(shí)現(xiàn)對緩沖區(qū)的互斥訪問
semaphore empty = n;        // 同步信號(hào)量,表示空閑緩沖區(qū)的數(shù)量
semaphore full = 0;         // 同步信號(hào)量先誉,表示非空閑緩沖區(qū)的數(shù)量(消息的數(shù)量)

producer() {                // 生產(chǎn)者進(jìn)程的任務(wù)是:不斷地生產(chǎn)產(chǎn)品湿刽,并放入緩沖區(qū)
    while (1) {
        生產(chǎn)一個(gè)消息;
        P(empty);           // 消費(fèi)一個(gè)空閑緩沖區(qū)
        P(mutex);           // 進(jìn)入臨界區(qū),獲取緩沖池的鎖(互斥信號(hào)量)
        把消息放入緩沖區(qū);
        V(mutex);           // 離開臨界區(qū)褐耳,釋放緩沖池的鎖(互斥信號(hào)量)
        V(full);            // 釋放一個(gè)滿的緩沖區(qū)(釋放一個(gè)消息)
    }
}

consumer() {
    while (1) {             // 消費(fèi)者進(jìn)程的任務(wù)是:不斷地取出緩沖區(qū)中的消息诈闺,然后消費(fèi)掉
        P(full);            // 消費(fèi)一個(gè)滿緩沖區(qū)(消費(fèi)一個(gè)消息)
        P(mutex);           // 進(jìn)入臨界區(qū),獲取緩沖池的鎖
        從緩沖區(qū)中取出一個(gè)消息;
        V(mutex);           // 離開臨界區(qū)铃芦,釋放緩沖池的鎖
        V(empty);           // 釋放一個(gè)空緩沖區(qū)
        消費(fèi)消息;
    }
}
image

注意:生產(chǎn)者-消費(fèi)者問題的易錯(cuò)點(diǎn)在于:在生產(chǎn)者-消費(fèi)者問題中雅镊,實(shí)現(xiàn)互斥的P操作必須在實(shí)現(xiàn)同步的P操作之后,否則會(huì)出現(xiàn)死鎖刃滓;因?yàn)閂操作不會(huì)導(dǎo)致進(jìn)程阻塞仁烹,所以V操作的順序無所謂,先釋放哪一個(gè)都可以咧虎。

image

注意2:如果緩沖區(qū)大小為1卓缰,有可能不需要設(shè)置互斥信號(hào)量mutex就可以實(shí)現(xiàn)互斥訪問緩沖區(qū)的功能,但是需要具體問題具體分析(當(dāng)然加上了也沒有問題)砰诵。

讀者-寫者問題

讀者-寫者問題為解決復(fù)雜的互斥問題提供了一個(gè)參考思路:設(shè)置互斥訪問的計(jì)數(shù)器變量count來記錄當(dāng)前正在訪問文件的進(jìn)程數(shù)征唬,可以用count的值判斷是第一個(gè)或最后一個(gè)讀進(jìn)程并做不同處理(加鎖、解鎖等)茁彭。如果對count變量的檢查和賦值不能“一氣呵成”會(huì)導(dǎo)致一些錯(cuò)誤总寒,就需要用到互斥信號(hào)量實(shí)現(xiàn)“一氣呵成”。

問題描述

有讀者和寫者兩組并發(fā)進(jìn)程理肺,共享一個(gè)文件摄闸。當(dāng)兩個(gè)以上的讀進(jìn)程同時(shí)訪問共享數(shù)據(jù)時(shí)不會(huì)產(chǎn)生副作用,但若某個(gè)寫進(jìn)程和其他進(jìn)程(讀或?qū)戇M(jìn)程)同時(shí)訪問共享數(shù)據(jù)時(shí)則可能導(dǎo)致數(shù)據(jù)不一致的錯(cuò)誤妹萨。因此要求:

  1. 允許多個(gè)讀者可以同時(shí)對文件執(zhí)行讀操作年枕;
  2. 只允許一個(gè)寫者往文件中寫信息;
  3. 任一寫者完成寫操作之前不允許其它讀者或?qū)懻吖ぷ鳎?/li>
  4. 寫者執(zhí)行操作前乎完,應(yīng)讓已有的讀者和寫者全部退出画切。

代碼

  1. 讀進(jìn)程優(yōu)先:只要有源源不斷的讀進(jìn)程在讀文件,寫進(jìn)程就需要一直阻塞等待囱怕,可能會(huì)導(dǎo)致寫進(jìn)程“餓死”的情況。
int count = 0;              // 用于記錄當(dāng)前有幾個(gè)讀進(jìn)程在訪問文件
semaphore rw = 1;           // 用于實(shí)現(xiàn)對共享文件的互斥訪問
semaphore mutex = 1;        // 用于實(shí)現(xiàn)對count變量的互斥訪問毫别,使得對count變量的檢查和賦值可以“一氣呵成”

writer() {                  // 寫進(jìn)程的工作很簡單:開始寫之前對共享文件加鎖娃弓,寫完后釋放鎖
    while (1) {
        P(rw);              // 獲取共享文件的鎖
        寫文件;
        V(rw);              // 釋放共享文件的鎖
    }
}

reader() {                  // 不同的讀進(jìn)程要負(fù)責(zé)加鎖和解鎖
    while (1) {
        P(mutex);           // 獲取count變量的鎖
        if (count == 0) {   // 第一個(gè)讀進(jìn)程要負(fù)責(zé)加鎖
            P(rw);          // 獲取共享文件的鎖
        }
        count++;            // 加鎖完成,讀者計(jì)數(shù)器加1
        V(mutex);           // 釋放count變量的鎖
        讀文件;
        P(mutex);           // 獲取count變量的鎖
        count--;            // 讀文件完成岛宦,讀者計(jì)數(shù)器減1
        if (count == 0) {   // 最后一個(gè)讀進(jìn)程負(fù)責(zé)解鎖
            V(rw);          // 釋放共享文件的鎖
        }
        V(mutex);           // 釋放count變量的鎖
    }
}
  1. 寫進(jìn)程優(yōu)先/讀寫公平法:有寫進(jìn)程請求訪問時(shí)台丛,應(yīng)禁止后續(xù)讀進(jìn)程的請求,且在無寫進(jìn)程的情況下才允許讀進(jìn)程再次運(yùn)行。

int count = 0;              // 用于記錄當(dāng)前有幾個(gè)讀進(jìn)程在訪問文件
semaphore rw = 1;           // 用于實(shí)現(xiàn)對共享文件的互斥訪問
semaphore mutex = 1;        // 用于實(shí)現(xiàn)對count變量的互斥訪問挽霉,使得對count變量的檢查和賦值可以“一氣呵成”
semaphore w = 1;            // 用于實(shí)現(xiàn)“寫優(yōu)先”

writer() {                  // 寫進(jìn)程的工作很簡單:開始寫之前對共享文件加鎖防嗡,寫完后釋放鎖
    while (1) {
        P(w);               // 獲取寫進(jìn)程的鎖
        P(rw);              // 獲取共享文件的鎖
        寫文件;
        V(rw);              // 釋放共享文件的鎖
        V(w);               // 釋放寫進(jìn)程的鎖
    }
}

reader() {                  // 不同的讀進(jìn)程要負(fù)責(zé)加鎖和解鎖
    while (1) {
        P(w);               // 獲取寫進(jìn)程的鎖
        P(mutex);           // 獲取count變量的鎖
        if (count == 0) {   // 第一個(gè)讀進(jìn)程要負(fù)責(zé)加鎖
            P(rw);          // 獲取共享文件的鎖
        }
        count++;            // 加鎖完成,讀者計(jì)數(shù)器加1
        V(mutex);           // 釋放count變量的鎖
        V(w);               // 釋放寫進(jìn)程的鎖侠坎,讓其它讀/寫進(jìn)程可以訪問共享文件
        讀文件;
        P(mutex);           // 獲取count變量的鎖
        count--;            // 讀文件完成蚁趁,讀者計(jì)數(shù)器減1
        if (count == 0) {   // 最后一個(gè)讀進(jìn)程負(fù)責(zé)解鎖
            V(rw);          // 釋放共享文件的鎖
        }
        V(mutex);           // 釋放count變量的鎖
    }
}

注意:這種算法中寫者不會(huì)“饑餓”,但也不是真正的“寫優(yōu)先”实胸,而是相對公平的先來先服務(wù)原則他嫡。

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

哲學(xué)家進(jìn)餐問題的關(guān)鍵在于解決進(jìn)程死鎖。這些進(jìn)程之間存在互斥關(guān)系庐完,但是與之前接觸到的互斥關(guān)系不同的地方在于每個(gè)進(jìn)程都需要同時(shí)持有兩個(gè)臨界資源钢属,因此就有產(chǎn)生死鎖的隱患。如果遇到了一個(gè)進(jìn)程需要同時(shí)持有多個(gè)臨界資源的情況门躯,應(yīng)該參考哲學(xué)家進(jìn)餐問題的思想淆党,分析進(jìn)程中是否會(huì)發(fā)生循環(huán)等待(是否會(huì)發(fā)生死鎖)。

問題描述

一張圓桌邊上坐著五名哲學(xué)家讶凉,每兩名哲學(xué)家之間的桌上擺上一根筷子染乌,兩根筷子中間是一碗米飯。哲學(xué)家們傾注畢生精力思考和進(jìn)餐缀遍,哲學(xué)家在思考時(shí)慕匠,并不影響他人。只有當(dāng)哲學(xué)家饑餓時(shí)域醇,才試圖拿起左台谊、右兩根筷子(一根一根地拿起)。若筷子已在他人手上譬挚,則需要等待锅铅。饑餓的哲學(xué)家只有同時(shí)拿到了兩根筷子才可以開始進(jìn)餐,進(jìn)餐完畢后减宣,放下筷子繼續(xù)思考盐须。

代碼

哲學(xué)家按順序編號(hào)為0~4,哲學(xué)家i左邊的筷子編號(hào)為i漆腌,右邊的筷子編號(hào)為(i + 1) % 5

  1. 可能產(chǎn)生死鎖的情況:5名哲學(xué)家都想要進(jìn)餐并分別拿起左邊筷子時(shí)贼邓,再想要拿起右邊筷子時(shí)就會(huì)被阻塞,產(chǎn)生了死鎖闷尿。
semaphore chopstick[5] = {1, 1, 1, 1, 1};

Pi() {                          // i號(hào)哲學(xué)家的進(jìn)程
    do {
    P(chopstick[i]);            // 取左邊筷子
    P(chopstick[(i + 1) % 5]);  // 取右邊筷子
    進(jìn)餐;
    V(chopstick[i]);            // 放下左邊筷子
    V(chopstick[(i + 1) % 5]);  // 放下右邊筷子
    思考;
    } while (1);
}
  1. 不會(huì)產(chǎn)生死鎖的情況
semaphore chopstick[5] = {1, 1, 1, 1, 1};
semaphore mutex = 1;                // 互斥取筷子的信號(hào)量

Pi() {
    do {
        P(mutex);                   // 獲得互斥量的鎖
        P(chopstick[i]);            // 取左邊筷子
        P(chopstick[(i + 1) % 5]);  // 取右邊筷子
        V(mutex);                   // 釋放互斥量的鎖
        進(jìn)餐;
        V(chopstick[i]);            // 放下左邊筷子
        V(chopstick[(i + 1) % 5]);  // 放下右邊筷子
        思考;
    } while (1);
}

吸煙者問題

吸煙者問題為解決“可以生產(chǎn)多個(gè)產(chǎn)品的單生產(chǎn)者”問題提供了一個(gè)思路塑径。關(guān)鍵在于如何用整型變量i實(shí)現(xiàn)輪流操作(類似于循環(huán)隊(duì)列中計(jì)算當(dāng)前指針位置時(shí)模隊(duì)列長度的操作)。若一個(gè)生產(chǎn)者要生產(chǎn)多種產(chǎn)品填具,那么各個(gè)V操作應(yīng)該放在各自對應(yīng)的“事件”發(fā)生之后的位置统舀。

問題描述

假設(shè)一個(gè)系統(tǒng)有三個(gè)抽煙者進(jìn)程和一個(gè)供應(yīng)者進(jìn)程。每個(gè)抽煙者不停地卷煙并抽掉它,但要卷起一支煙誉简,抽煙者需要有三種材料:煙草碉就、紙和膠水。三個(gè)抽煙者中闷串,第一個(gè)擁有煙草瓮钥,第二個(gè)擁有紙,第三個(gè)擁有膠水窿克。供應(yīng)者無限地提供三種材料骏庸,供應(yīng)者每次將兩種材料放到桌子上,擁有剩下那種材料的抽煙者卷一根煙并抽掉它年叮,并給供應(yīng)者一個(gè)信號(hào)告訴已完成具被,此時(shí)供應(yīng)者就會(huì)將另外兩種材料放到桌上,如此重復(fù)(讓三個(gè)抽煙者輪流地抽煙)只损。

代碼

int i = 0;                          // 用于實(shí)現(xiàn)“三個(gè)抽煙者輪流抽煙”
semaphore offer1 = 0;               // 桌上煙草和紙組合的數(shù)量
semaphore offer2 = 0;               // 桌上煙草和膠水組合的數(shù)量
semaphore offer3 = 0;               // 桌上紙和膠水組合的數(shù)量
semaphore finish = 0;               // 抽煙是否完成

provider() {                        // 擁有煙草的抽煙者
    while (1) {
        i = (i + 1) % 3;            // 實(shí)現(xiàn)循環(huán)提供三種組合一姿,即“三個(gè)抽煙者輪流抽煙”
        if (i == 0) {
            V(offer1);              // 提供煙草和紙
        } else if (i == 1) {
            V(offer2);              // 提供煙草和膠水
        } else if (i == 2) {
            V(offer3);              // 提供紙和膠水
        }
        把兩種材料放在桌子上;
        P(finish);                  // 等待抽煙者的完成信號(hào)
    }
}

smoker1() {                         // 擁有煙草的抽煙者
    while (1) {
        P(offer3);
        從桌子上拿走紙和膠水,卷成煙跃惫,抽掉叮叹;
        V(finish);
    }
}

smoker2() {                         // 擁有紙的抽煙者
    while (1) {
        P(offer2);
        從桌子上拿走煙草和膠水,卷成煙爆存,抽掉;
        V(finish);
    }
}

smoker3() {                         // 擁有膠水的抽煙者
    while (1) {
        P(offer1);
        從桌子上拿走煙草和紙蛉顽,卷成煙,抽掉;
        V(finish);
    }
}

進(jìn)程通信

進(jìn)程通信指的是進(jìn)程之間的信息交換先较。
進(jìn)程的互斥與同步只能稱為低級通信携冤,原因如下:

  1. 效率低:生產(chǎn)者每次只能向緩沖池投放一個(gè)產(chǎn)品(消息),消費(fèi)者每次只能從緩沖區(qū)中取得一個(gè)消息闲勺;
  2. 通信對用戶不透明:OS只為進(jìn)程間的通信提供了共享存儲(chǔ)器曾棕,關(guān)于進(jìn)程之間通信所需的共享數(shù)據(jù)的設(shè)置、數(shù)據(jù)的傳送菜循、進(jìn)程的互斥與同步都需要程序員自己實(shí)現(xiàn)翘地。

在進(jìn)程間需要傳送大量數(shù)據(jù)時(shí),應(yīng)該使用高級通信方式癌幕,主要特點(diǎn)為:

  1. 使用方便:通信過程對用戶是透明的衙耕;
  2. 高效地傳送大量數(shù)據(jù):用戶可以直接利用高級通信命令(原語)高效地傳送大量數(shù)據(jù)。

共享存儲(chǔ)器系統(tǒng)

在共享存儲(chǔ)器系統(tǒng)中勺远,相互通信的進(jìn)程共享某些數(shù)據(jù)結(jié)構(gòu)或共享存儲(chǔ)區(qū)臭杰,進(jìn)程之間能通過這些空間進(jìn)行通信。共享存儲(chǔ)器系統(tǒng)分為兩種類型:

  • 基于共享數(shù)據(jù)結(jié)構(gòu)的通信方式/低級方式:進(jìn)程公用某些數(shù)據(jù)結(jié)構(gòu)借以實(shí)現(xiàn)進(jìn)程之間的信息交換谚中。這種方式通信效率低下,屬于低級通信;
  • 基于共享存儲(chǔ)區(qū)的通信方式/高級方式:在內(nèi)存中劃出一塊共享存儲(chǔ)區(qū)域宪塔,進(jìn)程可通過對該共享區(qū)的讀或?qū)懡粨Q信息實(shí)現(xiàn)通信磁奖,OS只負(fù)責(zé)為通信進(jìn)程提供可共享使用的存儲(chǔ)空間和同步互斥工具,而數(shù)據(jù)交換則由用戶自己安排讀/寫指令完成某筐。

管道通信系統(tǒng)

管道是用于連接一個(gè)讀進(jìn)程和一個(gè)寫進(jìn)程以實(shí)現(xiàn)它們之間通信的一個(gè)共享文件比搭,又名pipe文件。

向管道(共享文件)提供輸入的發(fā)送進(jìn)程(寫進(jìn)程)以字符流的方式將數(shù)據(jù)送入管道南誊,接收管道輸出的接收進(jìn)程(讀進(jìn)程)則從管道中接收(讀)數(shù)據(jù)身诺。

為了協(xié)調(diào)上方的通信,管道機(jī)制必須提供以下三方面的協(xié)調(diào)能力:

  1. 互斥:當(dāng)一個(gè)進(jìn)程正在對管道進(jìn)行讀/寫操作時(shí)另一進(jìn)程必須等待抄囚;
  2. 同步:當(dāng)寫進(jìn)程把一定數(shù)量的數(shù)據(jù)寫入管道后便去等待霉赡,直到讀進(jìn)程取走數(shù)據(jù)后再喚醒;當(dāng)讀進(jìn)程讀空管道時(shí)也應(yīng)等待幔托,直到寫進(jìn)程將數(shù)據(jù)寫入管道后再喚醒穴亏;
  3. 確定對方是否存在:只有確定對方已存在時(shí)才能進(jìn)行通信。

注意:管道是半雙工通信的重挑,要事項(xiàng)全雙工通信需要兩個(gè)管道嗓化。

消息傳遞系統(tǒng)

在該機(jī)制中,進(jìn)程不必借助任何共享存儲(chǔ)區(qū)或數(shù)據(jù)結(jié)構(gòu)谬哀,而是以格式化的消息為單位將通信的數(shù)據(jù)封裝在消息中刺覆,并利用操作系統(tǒng)提供的一組通信命令(原語)在進(jìn)程間進(jìn)行消息傳遞,完成進(jìn)程間的數(shù)據(jù)交換史煎。

消息傳遞系統(tǒng)因?qū)崿F(xiàn)方式不同可分為兩類:

  1. 直接通信方式:發(fā)送進(jìn)程利用OS所提供的發(fā)送原語直接把消息發(fā)送給目標(biāo)進(jìn)程谦屑;
  2. 間接通信方式:發(fā)送和接收進(jìn)程都通過中間實(shí)體(郵箱)的方式進(jìn)行消息的發(fā)送和接收。

線程(Threads)的基本概念

線程的引入

引入進(jìn)程的目的是更好地使多道程序并發(fā)執(zhí)行劲室,提高資源利用率和系統(tǒng)吞吐量伦仍;引入線程的目的是減小程序在并發(fā)執(zhí)行時(shí)所付出的時(shí)空開銷,使OS具有更好的并發(fā)性很洋。

由于線程擁有許多傳統(tǒng)進(jìn)程所具有的特征充蓝,所以又被稱為“輕型進(jìn)程”,它是一個(gè)基本的CPU執(zhí)行單元喉磁,也是程序執(zhí)行流的最小單元谓苟,是進(jìn)程中的一個(gè)實(shí)體,是被系統(tǒng)獨(dú)立調(diào)度和分派的基本單位协怒。

  • 線程自己不擁有系統(tǒng)資源涝焙,它與同屬一個(gè)進(jìn)程的其它線程共享自己擁有的全部資源;
  • 一個(gè)線程可以創(chuàng)建和撤銷另一個(gè)線程孕暇,同一個(gè)進(jìn)程中的多個(gè)線程可以并發(fā)執(zhí)行仑撞;
  • 由于線程之間相互制約赤兴,線程在運(yùn)行中也具有間斷性;
  • 線程也有就緒隧哮、運(yùn)行桶良、阻塞三種狀態(tài)。

引入線程后沮翔,進(jìn)程只作為除CPU外的系統(tǒng)資源的分配單元陨帆,線程作為處理機(jī)的分配單元。

線程與進(jìn)程的比較

  1. 調(diào)度的基本單位:在傳統(tǒng)的OS中采蚀,進(jìn)程是作為獨(dú)立調(diào)度和分派的基本單位疲牵,也是能獨(dú)立運(yùn)行的基本單位。引入線程后榆鼠,線程是獨(dú)立單獨(dú)和分派的基本單位和能獨(dú)立運(yùn)行的基本單位纲爸,進(jìn)程是擁有資源的基本單位。線程切換時(shí)僅需保存和設(shè)置少量寄存器內(nèi)容璧眠,切換代價(jià)遠(yuǎn)低于進(jìn)程缩焦;在同一進(jìn)程中切換線程不會(huì)引起進(jìn)程的切換,從一個(gè)進(jìn)程的線程切換到另一個(gè)進(jìn)程中的線程時(shí)會(huì)引起進(jìn)程的切換责静;
  2. 并發(fā)性:在引入線程的OS中袁滥,不僅進(jìn)程之間可以并發(fā)執(zhí)行,線程之間也可以并發(fā)執(zhí)行灾螃,這使得OS具有更好的并發(fā)性题翻,從而能更加有效地提高系統(tǒng)資源的利用率和系統(tǒng)的吞吐量;
  3. 擁有資源:進(jìn)程是擁有資源的基本單位腰鬼,線程本身不擁有系統(tǒng)資源嵌赠,而僅有一點(diǎn)必不可少的、能獨(dú)立運(yùn)行的資源熄赡,比如在每個(gè)線程中應(yīng)具有一個(gè)線程控制塊TCB姜挺、程序計(jì)數(shù)器、保留局部變量彼硫、少數(shù)狀態(tài)參數(shù)和返回地址等的一組寄存器和堆棧炊豪。線程除了擁有自己的少量資源外,還允許多個(gè)線程共享該進(jìn)程所擁有的資源拧篮,如已打開的文件尖淘、定時(shí)器止剖、信號(hào)量機(jī)構(gòu)等的內(nèi)存空間和進(jìn)程申請到的I/O設(shè)備等;
  4. 獨(dú)立性:在同一進(jìn)程中的不同線程之間的獨(dú)立性要比不同進(jìn)程之間的獨(dú)立性低得多蔫劣。不同進(jìn)程的地址空間相互獨(dú)立油啤,同一進(jìn)程的不同線程共享進(jìn)程的內(nèi)存地址空間和資源冕广,進(jìn)程內(nèi)的線程對其他進(jìn)程不可見;進(jìn)程間通信需要進(jìn)程同步互斥手段來保證數(shù)據(jù)的一致性,而線程間可以直接讀/寫進(jìn)程數(shù)據(jù)段(如全局變量)進(jìn)行通信慧妄;
  5. 系統(tǒng)開銷:在創(chuàng)建和撤銷進(jìn)程時(shí),系統(tǒng)都要為之分配和回收PCB纫溃、內(nèi)存空間和I/O設(shè)備等資源腰涧,因此OS為此所付出的開銷明顯大于線程創(chuàng)建和撤銷時(shí)所付出的開銷;此外紊浩,由于一個(gè)進(jìn)程中的多個(gè)線程具有相同的地址空間,線程之間的同步和通信也比進(jìn)程簡單疗锐,在一些OS中坊谁,線程的切換、同步和通信都無需操作系統(tǒng)內(nèi)核的干預(yù)滑臊;
  6. 支持多處理機(jī)系統(tǒng):在多處理機(jī)系統(tǒng)中口芍,對于傳統(tǒng)的進(jìn)程,不管有多少處理機(jī)雇卷,該進(jìn)程都只能運(yùn)行在一個(gè)處理機(jī)上鬓椭;引入線程后,就可以將一個(gè)進(jìn)程中的多個(gè)線程分配到多個(gè)處理機(jī)上关划,使它們并行執(zhí)行小染,加快了進(jìn)程的執(zhí)行速度。

線程的屬性

多線程操作系統(tǒng)把線程作為獨(dú)立運(yùn)行或調(diào)度的基本單位贮折,此時(shí)進(jìn)程已經(jīng)不是一個(gè)基本的可執(zhí)行實(shí)體裤翩,進(jìn)程的“執(zhí)行”狀態(tài)實(shí)際上指的是進(jìn)程中的線程正在執(zhí)行。

線程的主要屬性如下:

  1. 線程不擁有系統(tǒng)資源调榄,每個(gè)線程擁有一個(gè)唯一的標(biāo)識(shí)符和一個(gè)線程控制塊TCB踊赠,線程控制塊記錄了線程執(zhí)行的寄存器和棧現(xiàn)場等信息每庆;
  2. 不同的線程可以執(zhí)行相同的程序筐带;
  3. 同一進(jìn)程中的不同線程共享該進(jìn)程所擁有的系統(tǒng)資源;
  4. 線程是處理機(jī)調(diào)度的基本單位缤灵,多個(gè)線程可以并發(fā)執(zhí)行伦籍;
  5. 線程在生命周期內(nèi)會(huì)經(jīng)歷就緒態(tài)、運(yùn)行態(tài)凤价、阻塞態(tài)等各種狀態(tài)的變化鸽斟。

線程的實(shí)現(xiàn)

線程有兩種實(shí)現(xiàn)方式:用戶級線程(ULT)和內(nèi)核級線程(KLT)。內(nèi)核級線程又稱為內(nèi)核支持的線程利诺。

在用戶級線程中富蓄,有關(guān)線程管理的所有工作都由應(yīng)用程序完成,內(nèi)核意識(shí)不到線程的存在慢逾,應(yīng)用程序可以使用線程庫設(shè)計(jì)成多線程程序立倍。

在內(nèi)核級線程中灭红,線程的管理工作由內(nèi)核完成,應(yīng)用程序沒有線程管理的代碼口注,只有一個(gè)內(nèi)核級線程的編程接口变擒,內(nèi)核為進(jìn)程及其內(nèi)部的每個(gè)線程維護(hù)上下文信息,調(diào)度也在內(nèi)核基于線程架構(gòu)的基礎(chǔ)上完成寝志。

有些系統(tǒng)中使用組合的方式的多線程實(shí)現(xiàn)娇斑,線程的創(chuàng)建在用戶空間中完成,線程的調(diào)度與同步也在應(yīng)用程序中進(jìn)行材部,一個(gè)應(yīng)用程序中的多個(gè)用戶級線程被映射到一些內(nèi)核級線程上毫缆。

多線程模型

多線程模型即用戶級線程和內(nèi)核級線程的連接方式。

  1. 多對一模型:將多個(gè)用戶級線程映射到一個(gè)內(nèi)核級線程上乐导,線程的管理在用戶空間完成苦丁。此模式中用戶級線程對操作系統(tǒng)不可見。優(yōu)點(diǎn):線程管理是在用戶空間進(jìn)行的物臂,效率較高旺拉;缺點(diǎn):一個(gè)線程在使用內(nèi)核服務(wù)時(shí)被阻塞會(huì)導(dǎo)致整個(gè)進(jìn)程被阻塞,多個(gè)線程不能很好地運(yùn)行在多處理機(jī)上棵磷;
  2. 一對一模型:每個(gè)用戶級線程映射到一個(gè)內(nèi)核級線程蛾狗。優(yōu)點(diǎn):一個(gè)線程被阻塞后另一個(gè)線程可以繼續(xù)執(zhí)行,并發(fā)能力較強(qiáng)泽本;缺點(diǎn):每創(chuàng)建一個(gè)用戶級線程都要?jiǎng)?chuàng)建一個(gè)內(nèi)核級線程淘太,創(chuàng)建線程的開銷比較大,會(huì)對應(yīng)用程序的性能造成影響规丽;
  3. 多對多模型:將n個(gè)用戶級線程映射到m個(gè)內(nèi)核級線程上蒲牧,m <= n。優(yōu)點(diǎn):既克服了多對一模型并發(fā)度不高的缺點(diǎn)赌莺,又克服了一對一模型創(chuàng)建進(jìn)程開銷較大的缺點(diǎn)冰抢,此外還擁有多對一模型和一對一模型的優(yōu)點(diǎn)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末艘狭,一起剝皮案震驚了整個(gè)濱河市挎扰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巢音,老刑警劉巖遵倦,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異官撼,居然都是意外死亡梧躺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門傲绣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掠哥,“玉大人巩踏,你說我怎么就攤上這事⌒螅” “怎么了塞琼?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長禁舷。 經(jīng)常有香客問我彪杉,道長,這世上最難降的妖魔是什么牵咙? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任在讶,我火速辦了婚禮,結(jié)果婚禮上霜大,老公的妹妹穿的比我還像新娘。我一直安慰自己革答,他們只是感情好战坤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著残拐,像睡著了一般途茫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上溪食,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天囊卜,我揣著相機(jī)與錄音,去河邊找鬼错沃。 笑死栅组,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的枢析。 我是一名探鬼主播玉掸,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼醒叁!你這毒婦竟也來了司浪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤把沼,失蹤者是張志新(化名)和其女友劉穎啊易,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饮睬,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡租谈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了续捂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垦垂。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宦搬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出劫拗,到底是詐尸還是另有隱情间校,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布页慷,位于F島的核電站憔足,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏酒繁。R本人自食惡果不足惜滓彰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望州袒。 院中可真熱鬧揭绑,春花似錦、人聲如沸郎哭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夸研。三九已至邦蜜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亥至,已是汗流浹背悼沈。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留姐扮,地道東北人絮供。 一個(gè)月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像溶握,于是被迫代替她去往敵國和親杯缺。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 2.1進(jìn)程的基本概念 要點(diǎn) 1.分析程序執(zhí)行順序睡榆、以及并發(fā)的特征 2.進(jìn)程的概念萍肆、特征與狀態(tài) 3.進(jìn)程控制塊及其組...
    一萌新一閱讀 2,222評論 0 0
  • 1.前趨圖和程序執(zhí)行 1)前趨圖: 有向無循環(huán)圖 (關(guān)注的是前趨關(guān)系,不能有循環(huán)) 2)程序順序執(zhí)行的特征: 1....
    Pakho柏豪閱讀 725評論 0 0
  • 2.2進(jìn)程控制與同步 一胀屿、進(jìn)程控制 1塘揣、進(jìn)程控制的基本過程: 1)進(jìn)程的創(chuàng)建 2)進(jìn)程的終止 3)進(jìn)程的阻塞與喚醒...
    6d9fe196fd45閱讀 243評論 0 0
  • 2.3信號(hào)量機(jī)制 1、信號(hào)量機(jī)制是一種卓有成效的進(jìn)程同步工具宿崭。 (一)整型信號(hào)量 1.信號(hào)量定義為一個(gè)整型量亲铡; 2...
    6d9fe196fd45閱讀 140評論 0 0
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友。感恩相遇奖蔓!感恩不離不棄赞草。 中午開了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,567評論 0 11