進(jìn)程
計算機上所有可運行的軟件,通常也包括操作系統(tǒng)蚯嫌,被組織成若干順序進(jìn)程(sequential process)搁痛,簡稱進(jìn)程(process)。
-
一個進(jìn)程就是一個正在執(zhí)行程序的實例锰提,包括程序計數(shù)器、寄存器和變量的當(dāng)前值芳悲。從概念上說立肘,每個進(jìn)程擁有它自己的虛擬CPU。當(dāng)然名扛,實際上真正的CPU在各進(jìn)程之間來回切換谅年。
- a)含有4道程序的多道程序;
- b)4個獨立的順序進(jìn)程的概念模型肮韧;
- c)在任意時刻僅有一個程序是活躍的融蹂。
一個進(jìn)程是某種類型的一個活動,它有程序弄企、輸入超燃、輸出以及狀態(tài)。單個處理器可以被若干進(jìn)程共享拘领,它使用某種調(diào)度算法決定何時停止一個進(jìn)程的工作意乓,并轉(zhuǎn)而為另一個進(jìn)程提供服務(wù)。
創(chuàng)建進(jìn)程
有4種主要事件導(dǎo)致進(jìn)程的創(chuàng)建:
1)系統(tǒng)初始化院究。
2)執(zhí)行了正在運行的進(jìn)程所調(diào)用的進(jìn)程創(chuàng)建系統(tǒng)調(diào)用洽瞬。
3)用戶請求創(chuàng)建一個新進(jìn)程本涕。
4)一個批處理作業(yè)的初始化业汰。
- 在UNIX系統(tǒng)中,只有一個系統(tǒng)調(diào)用可以用來創(chuàng)建新進(jìn)程:fork菩颖。這個系統(tǒng)調(diào)用會創(chuàng)建一個與調(diào)用進(jìn)程相同的副本样漆。在調(diào)用了fork后,這兩個進(jìn)程(父進(jìn)程和子進(jìn)程)擁有相同的存儲映像晦闰、同樣的環(huán)境字符串和同樣的打開文件放祟。這就是全部情形。通常呻右,子進(jìn)程接著執(zhí)行execve或一個類似的系統(tǒng)調(diào)用跪妥,以修改其存儲映像并運行一個新的程序。
- 在Windows中声滥,情形正相反眉撵,一個Win32函數(shù)調(diào)用CreateProcess既處理進(jìn)程的創(chuàng)建,也負(fù)責(zé)把正確的程序裝入新的進(jìn)程。該調(diào)用有10個參數(shù)纽疟,其中包括要執(zhí)行的程序罐韩、輸入給該程序的命令行參數(shù)、各種安全屬性污朽、有關(guān)打開的文件是否繼承的控制位散吵、優(yōu)先級信息、為該進(jìn)程(若有的話)所需要創(chuàng)建的窗口規(guī)格以及指向一個結(jié)構(gòu)的指針蟆肆,在該結(jié)構(gòu)中新創(chuàng)建進(jìn)程的信息被返回給調(diào)用者矾睦。
進(jìn)程的終止
進(jìn)程的終止通常由下列條件引起:
1)正常退出(自愿的)。
2)出錯退出(自愿的)炎功。
3)嚴(yán)重錯誤(非自愿)顷锰。
4)被其他進(jìn)程殺死(非自愿)。
- 多數(shù)進(jìn)程是由于完成了它們的工作而終止亡问。
- 進(jìn)程終止的第二個原因是進(jìn)程發(fā)現(xiàn)了嚴(yán)重錯誤官紫。例如,如果用戶鍵入命令
cc foo.c
要編譯程序foo.c州藕,但是該文件并不存在束世,于是編譯器就會退出。
- 進(jìn)程終止的第三個原因是由進(jìn)程引起的錯誤床玻,通常是由于程序中的錯誤所致毁涉。例如,執(zhí)行了一條非法指令锈死、引用不存在的內(nèi)存贫堰,或除數(shù)是零等。
- 第四種終止進(jìn)程的原因是待牵,某個進(jìn)程執(zhí)行一個系統(tǒng)調(diào)用通知操作系統(tǒng)殺死某個其他進(jìn)程其屏。在UNIX中,這個系統(tǒng)調(diào)用是kill缨该。在Win32中對應(yīng)的函數(shù)是TerminateProcess偎行。在這兩種情形中,“殺手”都必須獲得確定的授權(quán)以便進(jìn)行動作贰拿。
進(jìn)程的層次結(jié)構(gòu)
進(jìn)程創(chuàng)建了另一個進(jìn)程后蛤袒,父進(jìn)程和子進(jìn)程就以某種形式繼續(xù)保持關(guān)聯(lián)。子進(jìn)程自身可以創(chuàng)建更多的進(jìn)程膨更,組成一個進(jìn)程的層次結(jié)構(gòu)妙真。
在UNIX中,進(jìn)程和它的所有子女以及后裔共同組成一個進(jìn)程組荚守。當(dāng)用戶從鍵盤發(fā)出一個信號時珍德,該信號被送給當(dāng)前與鍵盤相關(guān)的進(jìn)程組中的所有成員(它們通常是在當(dāng)前窗口創(chuàng)建的所有活動進(jìn)程)癌椿。每個進(jìn)程可以分別捕獲該信號、忽略該信號或采取默認(rèn)的動作菱阵,即被該信號殺死踢俄。另一個例子,可以用來說明進(jìn)程層次的作用晴及,考慮UNIX在啟動時如何初始化自己都办。一個稱為init的特殊進(jìn)程出現(xiàn)在啟動映像中。當(dāng)它開始運行時虑稼,讀入一個說明終端數(shù)量的文件琳钉。接著,為每個終端創(chuàng)建一個新進(jìn)程蛛倦。這些進(jìn)程等待用戶登錄歌懒。如果有一個用戶登錄成功,該登錄進(jìn)程就執(zhí)行一個shell準(zhǔn)備接收命令溯壶。所接收的這些命令會啟動更多的進(jìn)程及皂,以此類推。這樣且改,在整個系統(tǒng)中验烧,所有的進(jìn)程都屬于以init為根的一棵樹。
Windows中沒有進(jìn)程層次的概念又跛,所有的進(jìn)程都是地位相同的碍拆。惟一類似于進(jìn)程層次的暗示是在創(chuàng)建進(jìn)程的時侯,父進(jìn)程得到一個特別的令牌(稱為句柄)慨蓝,該句柄可以用來控制子進(jìn)程感混。但是,它有權(quán)把這個令牌傳送給某個其他進(jìn)程礼烈,這樣就不存在進(jìn)程層次了弧满。在UNIX中,進(jìn)程就不能剝奪其子女的“繼承權(quán)”
進(jìn)程的狀態(tài)
這三種狀態(tài)是:
1)運行態(tài)(該時刻進(jìn)程實際占用CPU)济丘。
2)就緒態(tài)(可運行谱秽,但因為其他進(jìn)程正在運行而暫時停止)洽蛀。
3)阻塞態(tài)(除非某種外部事件發(fā)生摹迷,否則進(jìn)程不能運行)。
前兩種狀態(tài)在邏輯上是類似的郊供。處于這兩種狀態(tài)的進(jìn)程都可以運行峡碉,只是對于第二種狀態(tài)暫時沒有CPU分配給它。第三種狀態(tài)與前兩種狀態(tài)不同驮审,處于該狀態(tài)的進(jìn)程不能運行鲫寄,即使CPU空閑也不行吉执。
進(jìn)程的三種狀態(tài)之間有四種可能的轉(zhuǎn)換關(guān)系,如圖所示地来。
一個進(jìn)程可處于運行態(tài)戳玫、阻塞態(tài)和就緒態(tài),圖中顯示出各狀態(tài)之間的轉(zhuǎn)換
轉(zhuǎn)換2和3是由進(jìn)程調(diào)度程序引起的未斑,進(jìn)程調(diào)度程序是操作系統(tǒng)的一部分咕宿,進(jìn)程甚至感覺不到調(diào)度程序的存在。系統(tǒng)認(rèn)為一個運行進(jìn)程占用處理器的時間已經(jīng)過長蜡秽,決定讓其他進(jìn)程使用CPU時間時府阀,會發(fā)生轉(zhuǎn)換2。
在系統(tǒng)已經(jīng)讓所有其他進(jìn)程享有了它們應(yīng)有的公平待遇而重新輪到第一個進(jìn)程再次占用CPU運行時芽突,會發(fā)生轉(zhuǎn)換3试浙。
調(diào)度程序的主要工作就是決定應(yīng)當(dāng)運行哪個進(jìn)程、何時運行及它應(yīng)該運行多長時間寞蚌,這是很重要的一點田巴。
當(dāng)進(jìn)程等待的一個外部事件發(fā)生時(如一些輸入到達(dá)),則發(fā)生轉(zhuǎn)換4挟秤。
如果此時沒有其他進(jìn)程運行固额,則立即觸發(fā)轉(zhuǎn)換3,該進(jìn)程便開始運行煞聪。否則該進(jìn)程將處于就緒態(tài)斗躏,等待CPU空閑并且輪到它運行。
進(jìn)程的實現(xiàn)
為了實現(xiàn)進(jìn)程模型昔脯,操作系統(tǒng)維護(hù)著一張表格(一個結(jié)構(gòu)數(shù)組)啄糙,即進(jìn)程表(process table)。每個進(jìn)程占用一個進(jìn)程表項(進(jìn)程控制塊)云稚。該表項包含了進(jìn)程狀態(tài)的重要信息隧饼,包括程序計數(shù)器、堆棧指針静陈、內(nèi)存分配狀況燕雁、所打開文件的狀態(tài)、賬號和調(diào)度信息鲸拥,以及其他在進(jìn)程由運行態(tài)轉(zhuǎn)換到就緒態(tài)或阻塞態(tài)時必須保存的信息拐格,從而保證該進(jìn)程隨后能再次啟動,就像從未被中斷過一樣刑赶。
圖中展示了在一個典型系統(tǒng)中的關(guān)鍵字段捏浊。
第一列中的字段與進(jìn)程管理有關(guān)。
其他兩列分別與存儲管理和文件管理有關(guān)撞叨。
在了解進(jìn)程表后金踪,就可以對在單個(或每一個)CPU上如何維持多個順序進(jìn)程的錯覺做更多的闡述浊洞。與每一I/O類關(guān)聯(lián)的是一個稱作中斷向量(interrupt vector)的位置(靠近內(nèi)存底部的固定區(qū)域)。它包含中斷服務(wù)程序的入口地址胡岔。假設(shè)當(dāng)一個磁盤中斷發(fā)生時法希,用戶進(jìn)程3正在運行,則中斷硬件將程序計數(shù)器靶瘸、程序狀態(tài)字铁材,有時還有一個或多個寄存器壓入堆棧,計算機隨即跳轉(zhuǎn)到中斷向量所指示的地址奕锌。這些是硬件完成的所有操作著觉,然后軟件,特別是中斷服務(wù)例程就接管一切剩余的工作惊暴。
- 所有的中斷都從保存寄存器開始饼丘,對于當(dāng)前進(jìn)程而言,通常是在進(jìn)程表項中辽话。隨后肄鸽,會從堆棧中刪除由中斷硬件機制存入堆棧的那部分信息,并將堆棧指針指向一個由進(jìn)程處理程序所使用的臨時堆棧油啤。一些諸如保存寄存器值和設(shè)置堆棧指針等操作典徘,無法用C語言這一類高級語言描述,所以這些操作通過一個短小的匯編語言例程來完成益咬,通常該例程可以供所有的中斷使用逮诲,因為無論中斷是怎樣引起的,有關(guān)保存寄存器的工作則是完全一樣的幽告。
當(dāng)該例程結(jié)束后梅鹦,它調(diào)用一個C過程處理某個特定的中斷類型剩下的工作。(假定操作系統(tǒng)由C語言編寫冗锁,通常這是所有真實操作系統(tǒng)的選擇)齐唆。在完成有關(guān)工作之后,大概就會使某些進(jìn)程就緒冻河,接著調(diào)用調(diào)度程序箍邮,決定隨后該運行哪個進(jìn)程。隨后將控制轉(zhuǎn)給一段匯編語言代碼叨叙,為當(dāng)前的進(jìn)程裝入寄存器值以及內(nèi)存映射并啟動該進(jìn)程運行锭弊。下圖中總結(jié)了中斷處理和調(diào)度的過程。值得注意的是摔敛,各種系統(tǒng)之間某些細(xì)節(jié)會有所不同廷蓉。
當(dāng)該進(jìn)程結(jié)束時,操作系統(tǒng)顯示一個提示符并等待新的命令马昙。一旦它接到新命令桃犬,就裝入新的程序進(jìn)內(nèi)存,覆蓋前一個程序.
多道程序設(shè)計模型
采用多道程序設(shè)計可以提高CPU的利用率行楞。嚴(yán)格地說攒暇,如果進(jìn)程用于計算的平均時間是進(jìn)程在內(nèi)存中停留時間的20%,且內(nèi)存中同時有5個進(jìn)程子房,則CPU將一直滿負(fù)載運行形用。然而,這個模型在現(xiàn)實中過于樂觀证杭,因為它假設(shè)這5個進(jìn)程不會同時等待I/O田度。
更好的模型是從概率的角度來看CPU的利用率。假設(shè)一個進(jìn)程等待I/O操作的時間與其停留在內(nèi)存中時間的比為p解愤。當(dāng)內(nèi)存中同時有n個進(jìn)程時镇饺,則所有n個進(jìn)程都在等待I/O(此時CPU空轉(zhuǎn))的概率是pn 。CPU的利用率由下面的公式給出:
以n為變量的函數(shù)表示了CPU的利用率送讲,n稱為多道程序設(shè)計的道數(shù)(degree of multiprogramming)奸笤。
從完全精確的角度考慮,應(yīng)該指出此概率模型只是描述了一個大致的狀況哼鬓。它假設(shè)所有n個進(jìn)程是獨立的监右,即內(nèi)存中的5個進(jìn)程中,3個運行异希,2個等待健盒,是完全可接受的。但在單CPU中称簿,不能同時運行3個進(jìn)程味榛,所以當(dāng)CPU忙時,已就緒的進(jìn)程也必須等待CPU予跌。因而搏色,進(jìn)程不是獨立的。更精確的模型應(yīng)該用排隊論構(gòu)造券册,但我們的模型(當(dāng)進(jìn)程就緒時频轿,給進(jìn)程分配CPU,否則讓CPU空轉(zhuǎn))仍然是有效的烁焙,即使上圖的真實曲線會與圖中所畫的略有不同航邢。
雖然上圖的模型很簡單,很粗略骄蝇,它依然對預(yù)測CPU的性能很有效膳殷。