理解多線程編程,掌握什么是線程和進(jìn)程以及它們之間的關(guān)系很重要。
1. 何為進(jìn)程氓仲?
進(jìn)程就是執(zhí)行中的一段程序。一旦程序被裝載到了內(nèi)存中并準(zhǔn)備執(zhí)行得糜,它就是一個(gè)進(jìn)程敬扛,具備文本(text)、數(shù)據(jù)(data)和堆棧片段(stack)以及它自己的資源(像文件朝抖、對(duì)象句柄啥箭、設(shè)備、信號(hào)量治宣、互斥量急侥、管道等)。OS管理進(jìn)程侮邀,進(jìn)程相關(guān)的信息都包含在進(jìn)程信息塊的結(jié)構(gòu)中坏怪。它里面包含有進(jìn)程名字(進(jìn)程ID)、內(nèi)存和分配資源的指針绊茧、寄存器保存區(qū)以及優(yōu)先級(jí)铝宵,運(yùn)行所在的CPU,命令行參數(shù)和環(huán)境塊的指針等华畏。
進(jìn)程的屬性包含保存在進(jìn)程信息塊中的部分或全部信息鹏秋。I/O計(jì)數(shù)器和虛擬內(nèi)存操作計(jì)數(shù)器是記錄I/O操作類(lèi)型和數(shù)量以及進(jìn)程的線程所執(zhí)行虛擬內(nèi)存操作的變量。退出狀態(tài)是進(jìn)程終止的原因唯绍。異常/調(diào)試端口為進(jìn)程間通信渠道拼岳。當(dāng)進(jìn)程的線程之一產(chǎn)生一個(gè)異持μ埽或調(diào)試進(jìn)程時(shí)况芒,操作系統(tǒng)發(fā)送消息給異常/調(diào)試端口。
進(jìn)程的環(huán)境是一個(gè)由系統(tǒng)和用戶定義指針的集合叶撒,它為進(jìn)程設(shè)置缺省信息绝骚。環(huán)境變量協(xié)助定義進(jìn)程的行為。環(huán)境列表的創(chuàng)建和初始化由用戶完成祠够,其中一些變量具有系統(tǒng)初始化的缺省設(shè)置压汪。當(dāng)進(jìn)程運(yùn)行時(shí),它尋找這些變量古瓤,并根據(jù)它們調(diào)整自己的行為止剖。這些變量包括用戶初始工作目錄腺阳、當(dāng)前路徑以及搜索命令的目錄列表。還可以通過(guò)調(diào)用函數(shù)來(lái)創(chuàng)建和初始化特定進(jìn)程的變量(在此有時(shí)又被稱(chēng)做局部變量)穿香。
2. 進(jìn)程狀態(tài)
進(jìn)程狀態(tài)是進(jìn)程某時(shí)某刻所處的模式或條件亭引,它決定了將來(lái)的事件以及進(jìn)程可能進(jìn)入的狀態(tài)。
準(zhǔn)備執(zhí)行的進(jìn)程處于就緒狀態(tài)皮获,它位于就緒隊(duì)列中焙蚓。然后由OS scheduler從此隊(duì)列中挑選出一個(gè)進(jìn)程在處理器上執(zhí)行,此時(shí)被選進(jìn)程就處于運(yùn)行狀態(tài)洒宝。如果進(jìn)程等待某個(gè)事件的發(fā)生而不能執(zhí)行购公,則它就進(jìn)入阻塞狀態(tài)。就緒雁歌、運(yùn)行以及阻塞被看作激活狀態(tài)宏浩,是最常見(jiàn)的實(shí)現(xiàn)進(jìn)程狀態(tài)。
新建和空閑是新創(chuàng)建進(jìn)程的初始狀態(tài)靠瞎。此狀態(tài)下绘闷,進(jìn)程準(zhǔn)備執(zhí)行但尚不能運(yùn)行。
在單處理器系統(tǒng)中较坛,只能有一個(gè)進(jìn)程處于備用狀態(tài)(standby state)印蔗。它是就緒狀態(tài)之后、運(yùn)行狀態(tài)之前的狀態(tài)丑勤。掛起-就緒狀態(tài)和掛起-阻塞狀態(tài)是兩種掛起進(jìn)程執(zhí)行的狀態(tài)华嘹。此狀態(tài)下的進(jìn)程為非激活。
進(jìn)程完成執(zhí)行后法竞,退出系統(tǒng)耙厚,所有相關(guān)信息都被刪除,而且地址空間與相關(guān)資源也都被釋放岔霸。此時(shí)進(jìn)程為完成或終止?fàn)顟B(tài)薛躬。在釋放它之前,進(jìn)程則處于僵化狀態(tài)呆细。
進(jìn)程的不同狀態(tài)之間會(huì)根據(jù)外界事件型宝、自身?xiàng)l件等的變化而進(jìn)行相互轉(zhuǎn)換。
進(jìn)程狀態(tài)變化有不同的原因絮爷。對(duì)于就緒趴酣、運(yùn)行和阻塞狀態(tài)有4種可能的轉(zhuǎn)換:
1>. 分派(diapatch);
2>. 時(shí)間耗盡(timerunout)坑夯;
3>. 阻塞(block)岖寞;
4>. 喚醒(wakeup)。
當(dāng)進(jìn)程由就緒隊(duì)列中被提交給處理器柜蜈,此進(jìn)程就被分派了仗谆。它會(huì)運(yùn)行一段時(shí)間指巡,稱(chēng)做時(shí)間片(quantum)。如果時(shí)間段用完隶垮,進(jìn)程就會(huì)從運(yùn)行狀態(tài)返回到就緒狀態(tài)(此轉(zhuǎn)換稱(chēng)做時(shí)間耗盡)厌处;而如果進(jìn)程需要I/O或等待某事件的發(fā)生而不能繼續(xù)運(yùn)行,則會(huì)從運(yùn)行狀態(tài)轉(zhuǎn)換到阻塞狀態(tài)(這種轉(zhuǎn)換即為阻塞)岁疼。
進(jìn)程還可能被掛起阔涉,有以下一些原因:
1>. 系統(tǒng)運(yùn)行狀況不良或中斷了;
2>. 系統(tǒng)可能超載捷绒,把一些進(jìn)程掛起可能會(huì)減輕超載瑰排;
3>. 用戶可能決定掛起進(jìn)程,因?yàn)樗o了不正確的結(jié)果暖侨,將它置為掛起狀態(tài)后椭住,直到問(wèn)題得到更正為止;
4>. 為了等待另一個(gè)進(jìn)程同步執(zhí)行字逗,自動(dòng)進(jìn)入掛起狀態(tài)肥橙;
5>. 進(jìn)程請(qǐng)求I/O操作躏吊,而因?yàn)槟承┰虮啃龋瑢?duì)應(yīng)的資源不可用或I/O操作沒(méi)有發(fā)生刨摩,此時(shí)進(jìn)入掛起狀態(tài)。
就緒俭厚、運(yùn)行和阻塞進(jìn)程都可以被掛起户魏。如果阻塞進(jìn)程的資源不可用,則進(jìn)程可能被掛起挪挤,直到資源可用為止叼丑。而在運(yùn)行中,用戶可以因?yàn)檫M(jìn)程產(chǎn)生了不正確的結(jié)果而決定掛起它扛门。一旦問(wèn)題糾正后鸠信,它再被重新激活,回到就緒或阻塞狀態(tài)论寨。
一旦進(jìn)程執(zhí)行完成星立,它可能退出系統(tǒng),并銷(xiāo)毀進(jìn)程政基。此時(shí)它的所有資源將被釋放贞铣,而且定義進(jìn)程的所有信息,包括表或列表中的項(xiàng)都被刪除沮明,這是一個(gè)進(jìn)程的正常終止。也有可能進(jìn)程在完成執(zhí)行后窍奋,但其資源沒(méi)有被釋放荐健,與進(jìn)程相關(guān)的信息沒(méi)有被刪除酱畅,此時(shí)的進(jìn)程將處于僵化狀態(tài)。
3. 進(jìn)程優(yōu)先權(quán)
系統(tǒng)使用優(yōu)先權(quán)方案(priority scheme)來(lái)決定就緒進(jìn)程使用處理器的順序江场。進(jìn)程被分配一個(gè)優(yōu)先類(lèi)以及該類(lèi)中的優(yōu)先級(jí)(類(lèi)和級(jí)從低到高)纺酸。系統(tǒng)從就緒隊(duì)列中選擇一個(gè)最高優(yōu)先權(quán)進(jìn)程來(lái)使用處理器。同一類(lèi)中同一級(jí)別的就緒進(jìn)程按一種輪詢方式來(lái)使用處理器址否,在更高優(yōu)先權(quán)進(jìn)程進(jìn)入系統(tǒng)前餐蔬,每個(gè)進(jìn)程都有機(jī)會(huì)使用處理器。進(jìn)程由外部資源和系統(tǒng)分配優(yōu)先權(quán)佑附。子進(jìn)程繼承了父進(jìn)程的優(yōu)先權(quán)樊诺,之后它又可以對(duì)其進(jìn)行改變。如果沒(méi)有分配優(yōu)先權(quán)音同,則賦予它缺省優(yōu)先權(quán)词爬。
優(yōu)先權(quán)可以是動(dòng)態(tài),也可是靜態(tài)权均。進(jìn)程具有一個(gè)初始分配的優(yōu)先權(quán)顿膨,只保持短暫的時(shí)間。當(dāng)系統(tǒng)發(fā)生變化時(shí)叽赊,可能需要改變進(jìn)程的優(yōu)先權(quán)來(lái)增加系統(tǒng)的響應(yīng)速度恋沃。動(dòng)態(tài)優(yōu)先權(quán)方案可以幫助較低優(yōu)先權(quán)進(jìn)程使用處理器。高優(yōu)先權(quán)進(jìn)程可以降低為較低優(yōu)先權(quán)必指,而較低優(yōu)先權(quán)進(jìn)程可以提升優(yōu)先權(quán)芽唇。一個(gè)進(jìn)程可被分配 一個(gè)靜態(tài)高優(yōu)先權(quán)來(lái)確保它總是使用處理器。在某些系統(tǒng)中取劫,搶先進(jìn)程的優(yōu)先權(quán)值被降低匆笤,而等待進(jìn)程的優(yōu)先權(quán)值被提升。
4. 進(jìn)程上下文切換
進(jìn)程的上下文包括系統(tǒng)需要的進(jìn)程有關(guān)信息以及在重新啟動(dòng)進(jìn)程環(huán)境時(shí)需要的相關(guān)信息谱邪。上下文包含可執(zhí)行映像(executable image)炮捧、程序計(jì)數(shù)器(program counter)、寄存器(register)惦银、堆棧(stack)以及用于動(dòng)態(tài)和靜態(tài)變量的分配內(nèi)存咆课。系統(tǒng)可能也需要知道有關(guān)進(jìn)程狀態(tài)、進(jìn)程和用戶標(biāo)識(shí)扯俱、規(guī)劃和計(jì)數(shù)信息书蚪、優(yōu)先權(quán)以及I/O方面的信息。還需知道是否等待著某個(gè)事件以及進(jìn)程占有資源的信息迅栅。
5 進(jìn)程間關(guān)系
進(jìn)程創(chuàng)建后就被分配了一個(gè)獨(dú)立的地址空間殊校。文本片斷通過(guò)一個(gè)可執(zhí)行映像初始化。數(shù)據(jù)和堆棧片斷以及進(jìn)程的屬性都同時(shí)被初始化读存。進(jìn)程對(duì)應(yīng)的資源也被分配为流。進(jìn)程的環(huán)境包括工作目錄呕屎、標(biāo)準(zhǔn)輸入、輸出敬察、錯(cuò)誤秀睛、路徑等。它是一個(gè)獨(dú)立的實(shí)體莲祸,可以創(chuàng)建或產(chǎn)生其他進(jìn)程蹂安。原始進(jìn)程稱(chēng)做父(進(jìn)程),產(chǎn)生的進(jìn)程稱(chēng)做子(進(jìn)程)锐帜。子進(jìn)程可以反過(guò)來(lái)成為父進(jìn)程田盈,于是創(chuàng)建了一個(gè)進(jìn)程的樹(shù)或?qū)哟谓Y(jié)構(gòu)。
父和子進(jìn)程描述了它們之間的關(guān)系抹估。進(jìn)程的關(guān)系決定了進(jìn)程的初始化缠黍、終止以及父進(jìn)程對(duì)子進(jìn)程的控制。
Unix環(huán)境中药蜻,創(chuàng)建子進(jìn)程是對(duì)其父進(jìn)程的復(fù)制瓷式。子進(jìn)程具有父進(jìn)程地址空間的一份拷貝。父進(jìn)程和子進(jìn)程的數(shù)據(jù)和堆棧片斷是私有的语泽,但它們共享文本片斷贸典。子進(jìn)程和父進(jìn)程可以訪問(wèn)在兩種進(jìn)程地址空間之外創(chuàng)建的共享內(nèi)存區(qū)域。子進(jìn)程可以繼承父進(jìn)程的環(huán)境踱卵、優(yōu)先權(quán)廊驼、規(guī)劃屬性以及父進(jìn)程的部分資源(包括文件描述符)。
子進(jìn)程與父進(jìn)程是兩個(gè)相互獨(dú)立的進(jìn)程惋砂。它們具有獨(dú)立的程序和堆棧計(jì)數(shù)器妒挎。子進(jìn)程可以更改它的變量值而不影響父進(jìn)程。對(duì)于創(chuàng)建子進(jìn)程前父進(jìn)程打開(kāi)的文件和設(shè)備等資源西饵,子進(jìn)程可以立即訪問(wèn)酝掩,但創(chuàng)建子進(jìn)程后,子進(jìn)程就不能訪問(wèn)之后由父進(jìn)程分配的任何額外資源眷柔。父進(jìn)程也不能訪問(wèn)子進(jìn)程分配的任何資源期虾。
Unix環(huán)境中,直到子進(jìn)程返回退出代碼到其父進(jìn)程中時(shí)驯嘱,它才能得到釋放镶苞。如果父進(jìn)程不能接受退出代碼,或者由于該代碼被忽略鞠评,或者由于父進(jìn)程過(guò)期了茂蚓,那么子進(jìn)程就不能被釋放,將一直駐留在內(nèi)存中,直到它與另一個(gè)接受它的退出代碼的進(jìn)程聯(lián)合為止煌贴。
如果父子關(guān)系不再維持御板,子進(jìn)程可以終止和釋放锥忿,且與派生它的進(jìn)程無(wú)關(guān)牛郑。
當(dāng)父進(jìn)程掛起執(zhí)行,直到子進(jìn)程終止為止敬鬓,這些進(jìn)程就是同步執(zhí)行(synchronous execution)淹朋。
父和子進(jìn)程也可以異步運(yùn)行。如果父和子進(jìn)程相互獨(dú)立運(yùn)行钉答,這些進(jìn)程就是異步執(zhí)行础芍。
異步運(yùn)行的子進(jìn)程可以是分離進(jìn)程(detached process)。分離進(jìn)程是與其父進(jìn)程并發(fā)運(yùn)行数尿,但沒(méi)有從父進(jìn)程繼承任何資源的子進(jìn)程仑性。父進(jìn)程終止時(shí),它們不會(huì)終止右蹦。它們與父進(jìn)程分離诊杆。父進(jìn)程可以消滅分離的子進(jìn)程。
6. 進(jìn)程映射
進(jìn)程有3個(gè)片斷:文本片斷何陆、堆棧片斷以及數(shù)據(jù)片斷晨汹。進(jìn)程的地址空間既有物理模型也有邏輯模型。物理模型有關(guān)進(jìn)程如何實(shí)際保存在RAM中贷盲。邏輯模型在布局的底端有文本斷淘这、然后是數(shù)據(jù)斷,堆棧斷則位于頂部巩剖。
7. 進(jìn)程資源
資源指進(jìn)程執(zhí)行任務(wù)所使用的硬件設(shè)備和軟件素材铝穷。它可以是進(jìn)程在任何給定時(shí)間使用的任何東西,可以是數(shù)據(jù)源或信息佳魔,或者是顯示數(shù)據(jù)或信息的方式曙聂。進(jìn)程可以使用由操作系統(tǒng)支持和管理的各種不同類(lèi)型的資源。一些資源為多個(gè)進(jìn)程所共享吃引。這樣的資源允許多個(gè)進(jìn)程并發(fā)訪問(wèn)筹陵,或者在允許另一個(gè)進(jìn)程訪問(wèn)前暫時(shí)只允許單個(gè)進(jìn)程的訪問(wèn)。
基本的資源類(lèi)型有如下三種:
1>. 硬件镊尺;
2>. 軟件朦佩;
3>. 數(shù)據(jù)。
硬件資源為物理設(shè)備庐氮。像處理器语稠,主內(nèi)存和RAM,以及I/O設(shè)備。
數(shù)據(jù)是另一種資源仙畦。進(jìn)程可以使用和操縱數(shù)據(jù)(比如文件输涕、對(duì)象和句柄)、系統(tǒng)數(shù)據(jù)(比如環(huán)境變量)以及全局定義變量(比如信號(hào)量和互斥量)慨畸±晨玻可以通過(guò)使用信號(hào)量(semaphore)、互斥量(mutex)寸士、臨界區(qū)(critical section)等來(lái)實(shí)現(xiàn)同步檐什。
軟件資源可以是其他進(jìn)程或動(dòng)態(tài)鏈接庫(kù)。共享軟件資源的進(jìn)程共享程序的一個(gè)拷貝弱卡,但擁有數(shù)據(jù)的單獨(dú)拷貝乃正。程序的進(jìn)程虛擬地址被映射到相同的物理內(nèi)存位置。使用時(shí)不發(fā)生變化的程序可以被多個(gè)進(jìn)程使用婶博。使用時(shí)可能發(fā)生變化的程序在進(jìn)程每次使用它時(shí)重新初始化瓮具。
為了讓系統(tǒng)區(qū)分各個(gè)進(jìn)程,以確保足夠的系統(tǒng)操作性能凡人。進(jìn)程可以給進(jìn)程任意分配優(yōu)先權(quán)名党。可以基于進(jìn)程使用的資源分配進(jìn)程優(yōu)先權(quán)划栓。通信密集進(jìn)程需要相對(duì)高的優(yōu)先權(quán)兑巾。使用或控制時(shí)間敏感設(shè)備的進(jìn)程甚至需要更高的優(yōu)先級(jí)。