C++面向對象多線程學習筆記_進程

理解多線程編程,掌握什么是線程和進程以及它們之間的關系很重要。

1. 何為進程?

進程就是執行中的一段程序。一旦程序被裝載到了內存中并準備執行,它就是一個進程,具備文本(text)、數據(data)和堆棧片段(stack)以及它自己的資源(像文件、對象句柄、設備、信號量、互斥量、管道等)。OS管理進程,進程相關的信息都包含在進程信息塊的結構中。它里面包含有進程名字(進程ID)、內存和分配資源的指針、寄存器保存區以及優先級,運行所在的CPU,命令行參數和環境塊的指針等。

進程的屬性包含保存在進程信息塊中的部分或全部信息。I/O計數器和虛擬內存操作計數器是記錄I/O操作類型和數量以及進程的線程所執行虛擬內存操作的變量。退出狀態是進程終止的原因。異常/調試端口為進程間通信渠道。當進程的線程之一產生一個異常或調試進程時,操作系統發送消息給異常/調試端口。

進程的環境是一個由系統和用戶定義指針的集合,它為進程設置缺省信息。環境變量協助定義進程的行為。環境列表的創建和初始化由用戶完成,其中一些變量具有系統初始化的缺省設置。當進程運行時,它尋找這些變量,并根據它們調整自己的行為。這些變量包括用戶初始工作目錄、當前路徑以及搜索命令的目錄列表。還可以通過調用函數來創建和初始化特定進程的變量(在此有時又被稱做局部變量)。

2. 進程狀態

進程狀態是進程某時某刻所處的模式或條件,它決定了將來的事件以及進程可能進入的狀態。

準備執行的進程處于就緒狀態,它位于就緒隊列中。然后由OS scheduler從此隊列中挑選出一個進程在處理器上執行,此時被選進程就處于運行狀態。如果進程等待某個事件的發生而不能執行,則它就進入阻塞狀態。就緒、運行以及阻塞被看作激活狀態,是最常見的實現進程狀態。

新建和空閑是新創建進程的初始狀態。此狀態下,進程準備執行但尚不能運行。

在單處理器系統中,只能有一個進程處于備用狀態(standby state)。它是就緒狀態之后、運行狀態之前的狀態。掛起-就緒狀態和掛起-阻塞狀態是兩種掛起進程執行的狀態。此狀態下的進程為非激活。

進程完成執行后,退出系統,所有相關信息都被刪除,而且地址空間與相關資源也都被釋放。此時進程為完成或終止狀態。在釋放它之前,進程則處于僵化狀態。

進程的不同狀態之間會根據外界事件、自身條件等的變化而進行相互轉換。

進程狀態變化有不同的原因。對于就緒、運行和阻塞狀態有4種可能的轉換:

1>. 分派(diapatch);

2>. 時間耗盡(timerunout);

3>. 阻塞(block);

4>. 喚醒(wakeup)。

當進程由就緒隊列中被提交給處理器,此進程就被分派了。它會運行一段時間,稱做時間片(quantum)。如果時間段用完,進程就會從運行狀態返回到就緒狀態(此轉換稱做時間耗盡);而如果進程需要I/O或等待某事件的發生而不能繼續運行,則會從運行狀態轉換到阻塞狀態(這種轉換即為阻塞)。

進程還可能被掛起,有以下一些原因:

1>. 系統運行狀況不良或中斷了;

2>. 系統可能超載,把一些進程掛起可能會減輕超載;

3>. 用戶可能決定掛起進程,因為它給了不正確的結果,將它置為掛起狀態后,直到問題得到更正為止;

4>. 為了等待另一個進程同步執行,自動進入掛起狀態;

5>. 進程請求I/O操作,而因為某些原因,對應的資源不可用或I/O操作沒有發生,此時進入掛起狀態。

就緒、運行和阻塞進程都可以被掛起。如果阻塞進程的資源不可用,則進程可能被掛起,直到資源可用為止。而在運行中,用戶可以因為進程產生了不正確的結果而決定掛起它。一旦問題糾正后,它再被重新激活,回到就緒或阻塞狀態。

一旦進程執行完成,它可能退出系統,并銷毀進程。此時它的所有資源將被釋放,而且定義進程的所有信息,包括表或列表中的項都被刪除,這是一個進程的正常終止。也有可能進程在完成執行后,但其資源沒有被釋放,與進程相關的信息沒有被刪除,此時的進程將處于僵化狀態。

3. 進程優先權

系統使用優先權方案(priority scheme)來決定就緒進程使用處理器的順序。進程被分配一個優先類以及該類中的優先級(類和級從低到高)。系統從就緒隊列中選擇一個最高優先權進程來使用處理器。同一類中同一級別的就緒進程按一種輪詢方式來使用處理器,在更高優先權進程進入系統前,每個進程都有機會使用處理器。進程由外部資源和系統分配優先權。子進程繼承了父進程的優先權,之后它又可以對其進行改變。如果沒有分配優先權,則賦予它缺省優先權。

優先權可以是動態,也可是靜態。進程具有一個初始分配的優先權,只保持短暫的時間。當系統發生變化時,可能需要改變進程的優先權來增加系統的響應速度。動態優先權方案可以幫助較低優先權進程使用處理器。高優先權進程可以降低為較低優先權,而較低優先權進程可以提升優先權。一個進程可被分配 一個靜態高優先權來確保它總是使用處理器。在某些系統中,搶先進程的優先權值被降低,而等待進程的優先權值被提升。

4. 進程上下文切換

進程的上下文包括系統需要的進程有關信息以及在重新啟動進程環境時需要的相關信息。上下文包含可執行映像(executable image)、程序計數器(program counter)、寄存器(register)、堆棧(stack)以及用于動態和靜態變量的分配內存。系統可能也需要知道有關進程狀態、進程和用戶標識、規劃和計數信息、優先權以及I/O方面的信息。還需知道是否等待著某個事件以及進程占有資源的信息。

5 進程間關系

進程創建后就被分配了一個獨立的地址空間。文本片斷通過一個可執行映像初始化。數據和堆棧片斷以及進程的屬性都同時被初始化。進程對應的資源也被分配。進程的環境包括工作目錄、標準輸入、輸出、錯誤、路徑等。它是一個獨立的實體,可以創建或產生其他進程。原始進程稱做父(進程),產生的進程稱做子(進程)。子進程可以反過來成為父進程,于是創建了一個進程的樹或層次結構。

父和子進程描述了它們之間的關系。進程的關系決定了進程的初始化、終止以及父進程對子進程的控制。

Unix環境中,創建子進程是對其父進程的復制。子進程具有父進程地址空間的一份拷貝。父進程和子進程的數據和堆棧片斷是私有的,但它們共享文本片斷。子進程和父進程可以訪問在兩種進程地址空間之外創建的共享內存區域。子進程可以繼承父進程的環境、優先權、規劃屬性以及父進程的部分資源(包括文件描述符)。

子進程與父進程是兩個相互獨立的進程。它們具有獨立的程序和堆棧計數器。子進程可以更改它的變量值而不影響父進程。對于創建子進程前父進程打開的文件和設備等資源,子進程可以立即訪問,但創建子進程后,子進程就不能訪問之后由父進程分配的任何額外資源。父進程也不能訪問子進程分配的任何資源。

Unix環境中,直到子進程返回退出代碼到其父進程中時,它才能得到釋放。如果父進程不能接受退出代碼,或者由于該代碼被忽略,或者由于父進程過期了,那么子進程就不能被釋放,將一直駐留在內存中,直到它與另一個接受它的退出代碼的進程聯合為止。

如果父子關系不再維持,子進程可以終止和釋放,且與派生它的進程無關。

當父進程掛起執行,直到子進程終止為止,這些進程就是同步執行(synchronous execution)。

父和子進程也可以異步運行。如果父和子進程相互獨立運行,這些進程就是異步執行。

異步運行的子進程可以是分離進程(detached process)。分離進程是與其父進程并發運行,但沒有從父進程繼承任何資源的子進程。父進程終止時,它們不會終止。它們與父進程分離。父進程可以消滅分離的子進程。

6. 進程映射

進程有3個片斷:文本片斷、堆棧片斷以及數據片斷。進程的地址空間既有物理模型也有邏輯模型。物理模型有關進程如何實際保存在RAM中。邏輯模型在布局的底端有文本斷、然后是數據斷,堆棧斷則位于頂部。

7. 進程資源

資源指進程執行任務所使用的硬件設備和軟件素材。它可以是進程在任何給定時間使用的任何東西,可以是數據源或信息,或者是顯示數據或信息的方式。進程可以使用由操作系統支持和管理的各種不同類型的資源。一些資源為多個進程所共享。這樣的資源允許多個進程并發訪問,或者在允許另一個進程訪問前暫時只允許單個進程的訪問。

基本的資源類型有如下三種:

1>. 硬件;

2>. 軟件;

3>. 數據。

硬件資源為物理設備。像處理器,主內存和RAM,以及I/O設備。

數據是另一種資源。進程可以使用和操縱數據(比如文件、對象和句柄)、系統數據(比如環境變量)以及全局定義變量(比如信號量和互斥量)。可以通過使用信號量(semaphore)、互斥量(mutex)、臨界區(critical section)等來實現同步。

軟件資源可以是其他進程或動態鏈接庫。共享軟件資源的進程共享程序的一個拷貝,但擁有數據的單獨拷貝。程序的進程虛擬地址被映射到相同的物理內存位置。使用時不發生變化的程序可以被多個進程使用。使用時可能發生變化的程序在進程每次使用它時重新初始化。

為了讓系統區分各個進程,以確保足夠的系統操作性能。進程可以給進程任意分配優先權。可以基于進程使用的資源分配進程優先權。通信密集進程需要相對高的優先權。使用或控制時間敏感設備的進程甚至需要更高的優先級。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容