一、前言
之前已經介紹了作業系統的各個模組,現在來具體深入學習作業系統中的程式管理。
二、程式的基本概念
在未配置OS的系統中,程式的執行方式是順序執行,即必須在一個程式執行完成後,才允許另外一個程式執行;在多道程式環境下,則允許多個程式併發執行。也正是程式的併發執行,才導致引入程式。
2.1 程式的順序執行
通常可以把一個應用程式分成若干個程式段,在各程式段之間,必須按照某種先後次序順序執行,僅當前一操作(程式段)執行完後,才能執行後繼操作。如典型的輸入->計算->列印任務就是順序執行。
程式順序執行時的特徵如下
① 順序性,處理機的操作嚴格按照程式鎖規定的順序執行,即每一操作必須在上一個操作結束之後開始。
② 封閉性,程式是在封閉的環境下執行的,即程式執行時獨佔全機資源,資源的狀態(除初始狀態外)只有本程式才能改變它,程式一旦開始執行,其執行結果不受外界因素影響。
③ 可再現性,只要程式執行時的環境和初始條件相同,當程式重複執行時,無論它是從頭到尾不停頓地執行,還是走走停停地執行,都將獲得相同的結果。
在程式順序執行時的特徵,為程式設計師檢測和校正程式的錯誤帶來了很大的方便。
2.2 程式的併發執行
多個程式可以併發執行,併發執行可以提高CPU的效率和系統吞吐率。其特徵如下
① 間斷性,程式在併發執行時,由於它們共享系統資源,以及為完成同一項任務而相互合作,致使在這些併發執行的程式之間,形成了相互制約的關係。如計算操作必須在輸入操作之後。
② 失去封閉性,程式在併發執行時,是多個程式共享系統中的各種資源,因而這些資源的狀態將由多個程式來改變,只是程式的執行失去了封閉性,這樣,某程式在執行時,必然會收到其他程式的影響。如當某個程式佔用了處理機資源後,另外一個程式必須等待。
③ 不可再現性,程式在併發執行時,由於失去了封閉性,也將導致其再失去可再現性。可能由於不同的操作順序產生不同的結果。
2.3 程式的特徵
由於程式併發執行時,它們失去了封閉性,間斷性和不可再現性,這決定了一般的程式是不能參與併發執行的,因為程式執行的結果是不可再現的。這樣,程式的執行也就失去了意義,為了能夠是程式能夠正確的併發,引入了程式的概念。程式具有如下的特徵。
① 結構特性,為使程式能夠獨立執行,應為之配置一程式控制塊,即PCB(Process Control Block)。而程式段、相關的資料段和PCB三部分構成程式實體。所謂建立程式,實質上是建立程式實體中的PCB,撤銷程式也是撤銷程式中的PCB。
② 動態性,進行的實質是程式實體的一次執行過程,因此,動態性是程式最基本的特性,程式實體是有一個的生命週期,而程式則只是一組有序指令的集合,並存放在某種介質上(如硬碟),其本身不具有運動的含義,因而是靜態的。
③ 併發性,多個程式實體同存於記憶體中,並且能夠在一段時間內同時執行。併發性是程式的重要特徵, 同時也成為OS的重要特徵。
④ 獨立性,程式實體是一個能獨立執行、獨立分配資源和獨立接受排程的基本單位。凡未建立PCB的程式都不能作為一個獨立的單位參與執行。
⑤ 非同步性,程式按各自獨立的、不可預知的速度向前推進,或者說程式實體按照非同步方式執行。
程式是程式實體的執行過程,是系統進行資源分配和排程(線上程未出現之前)的一個獨立單位。
2.4 程式的狀態
程式執行時的間斷性決定了程式可能具有多種狀態,最基本的三種狀態如下
① 就緒狀態,當程式已分配到除CPU以外的所有必要資源後,只要再獲得CPU,就可以立即執行,程式這時的狀態稱為就緒狀態。在一個系統中可能多個程式處於就緒狀態,通常將它們排成一個佇列,稱為就緒佇列。
② 執行狀態,程式已獲得CPU,其程式正在執行。在單處理機系統中,只有一個程式處於執行狀態,在多處理機系統中,則有多個程式處於執行狀態。
③ 阻塞狀態,處於執行狀態的執行緒由於發生某事件而暫停無法繼續執行時,便放棄處理機而處於暫停狀態,此時程式的狀態稱為阻塞狀態,或等待狀態或封鎖狀態。如IO請求,申請快取空間等,處於阻塞狀態的程式也會排成一個佇列,可能還會根據不同的阻塞原因排成多個佇列。
說明:上圖表示三種基本狀態之間的相互轉化。
除了上述三種基本狀態外,在一些系統中,新增了掛起狀態,引入掛起狀態的原因如下
① 終端使用者的請求,當終端使用者在自己的程式執行期間發現有可疑問題時,希望暫時使自己的程式靜止下來,即使正在執行的程式暫停執行;若此時使用者程式正處於就緒狀態而未執行,則該程式暫不接受排程,以便使用者研究其執行情況或對程式進行修改,這種狀態就稱為掛起狀態。
② 父程式請求,有時父程式希望掛起自己的某個子程式,以便考查和修改該子程式,或者協調各子程式間的活動。
③ 負荷調節的需要,當實時系統中的工作負荷較重,已可能影響到對實時任務的控制時,可由系統把一些不重要的程式掛起,以保證系統能夠正常執行。
④ 作業系統的需要,作業系統有時希望掛起某些程式,以便檢查執行中的資源使用情況或進行記賬。
引入了掛起狀態後,又增加了如下幾種狀態的轉化
① 活動就緒->靜止就緒,當程式處於未被掛起的就緒狀態時,稱為活動就緒狀態;當掛起時,變為靜止就緒狀態,處於靜止就緒狀態的程式不接受排程。
② 活動阻塞->靜止阻塞,當程式處於未被掛起的阻塞狀態時,稱為活動阻塞狀態;當掛起時,變為靜止阻塞狀態,處於該狀態的程式在其所期待的事件發生後,將從靜止阻塞變為靜止就緒。
③ 靜止就緒->活動就緒,使用啟用原語啟用。
④ 靜止阻塞->活動阻塞,使用啟用原語啟用。
為了程式的管理,還存在著兩種常見的狀態,即建立狀態和終止狀態。
① 建立狀態,建立一個程式一般需要兩步。首先,為一個新程式常見PCB,並填寫必要的管理資訊;其次,把該程式轉入就緒狀態並插入就緒佇列之中。當建立一個新程式時,系統為其分配了PCB,填寫了程式標誌等資訊,但由於該程式所必需的資源或其他資訊(如記憶體)尚未分配等,此時,程式雖擁有了PCB,但是其自身卻未進入記憶體,即建立工作尚未完成,此時程式還不能被排程執行,其所處的狀態就是建立狀態。
② 終止狀態,程式的終止也需要兩步。首先,等待作業系統進行善後處理,其次,將其PCB清零,並將PCB空間返回給作業系統。進入終止狀態的程式以後不能再執行,但是在作業系統中任然保留一個記錄,其中儲存狀態碼和一些計時統計資料,供其它程式收集,一旦其它程式完成對終止狀態程式的資訊提取後,作業系統將刪除該程式。
說明:上述為七種狀態之間的轉化。
2.5 程式控制塊
2.5.1 程式控制塊的作用
為了描述和控制程式的執行,系統為每個程式定義了一個資料結構,程式控制塊PCB,它是程式實體的一部分,是作業系統中最重要的記錄型資料結構,PCB中記錄了作業系統所需的,用於描述程式當前情況以及控制程式執行的全部資訊。
程式控制塊的作用是使一個在多道程式環境下能獨立執行的程式,成為一個能獨立執行的基本單位,一個能與其他程式併發執行的程式。或者說,OS是根據PCB來對併發執行的程式進行控制和管理的。PCB是程式存在的唯一標識。
當建立一個程式時,就為它建立一個PCB,程式結束時又回收其PCB,程式於是隨之消亡,PCB可以被作業系統中的多個模組讀或修改,如被排程程式、資源分配程式、中斷處理程式及監督分析程式等讀或修改,因為PCB是經常被系統訪問,尤其是被執行頻率很高的程式及分派程式訪問,故PCB應常駐記憶體。系統將所有的PCB組織成若干個連結串列(或佇列),存放在作業系統中專門開闢的PCB區內。
2.5.1 程式控制塊的資訊
程式控制塊PCB主要包含如下資訊。
① 程式識別符號,用於唯一地標識一個程式,有內部識別符號(由系統賦予的唯一一個數字,通常為程式的序號,為方便系統使用)和外部識別符號(由建立者提供,可描述程式的家族關係)。
② 處理機的狀態,當處理機被中斷時,其暫存器的資訊都必須儲存在程式的PCB中,以便該程式重新執行時,能從斷點繼續執行。
③ 程式排程資訊,包括程式狀態(指明程式的當前狀態,作為程式排程和對換時的依據),程式優先順序(用於描述程式使用處理機的優先順序別,優先順序高的程式應該優先獲取處理機),程式排程所需的其他資訊(與程式排程演算法有關,如程式已等待CPU的時間總和,程式已執行的時間總和等),事件(程式由執行狀態轉變為阻塞狀態所等待發生的事件,即阻塞原因)。
④ 程式控制資訊,包括程式和資料的地址(程式的程式和資料所在的記憶體或外存首址,以便在排程該程式時,能從PCB中找到其程式和資料),程式同步和通訊機制(實現程式同步和程式通訊時必需的機制,如訊息佇列指標,訊號量等),資源清單(除CPU以外的程式所需的全部資源以及已經分配到該程式的資源的清單),連結地址(本程式PCB所在佇列中的下一個程式的PCB的首地址)。
2.5.3 程式控制塊的組織方式
為了有效的對PCB進行管理,應該用適當的方式將這些PCB組織起來,常用的組織方式如下
① 連結方式,把具有同一狀態的PCB,連結成一個佇列,這樣可以形成若干就緒佇列、阻塞佇列和空白佇列等,優先順序高的程式的PCB排在前面。
② 索引方式,系統根據所有程式的狀態建立幾張索引表,如就緒索引表,阻塞索引表等,並把各索引表在記憶體的首地址記錄在記憶體的一些專用單元中,在每個索引表的表目中,記錄具有相應狀態的某個PCB在PCB表中的地址。
三、程式控制
3.1 程式的建立
一個程式可以建立一個子程式,子程式會繼承父程式所擁有的資源,如繼承父程式開啟的檔案、分配到的緩衝區等,當子程式被撤銷時,應該講其從父程式哪裡獲得的資源歸還給父程式,此外,撤銷父程式時,也必須同時撤銷其所有的子程式。
引起建立程式的事件如下
① 使用者登入。② 作業排程。③ 提供服務。④ 應用請求。
程式建立的步驟如下
① 申請空白PCB,為新程式申請獲得唯一的數字識別符號,並從PCB集合中索取一個空白的PCB。
② 為新程式分配資源,為新程式的程式和資料以及使用者棧分配必要的記憶體空間。
③ 初始化程式控制塊,PCB的初始化包括:初始化標識資訊,將系統分配的識別符號和父程式識別符號填入新的PCB中;初始化處理機狀態資訊,使程式計數器指向程式的入口地址,使棧指標指向棧頂;初始化處理機控制資訊,將程式的狀態設定為就緒狀態或靜止就緒狀態。
④ 將新程式插入到就緒佇列,如果程式就緒佇列能夠接納新程式,便將新程式插入就緒佇列。
3.2 程式的終止
引起程式終止的事件如下
① 正常結束,在任何計算機系統中,都應有一個用於表示程式已經執行完成的指示。
② 異常結束,在程式執行期間,由於出現某些錯誤和故障而迫使程式終止。如越界錯誤(程式所訪問的儲存區已越出該程式的區域),保護錯(程式試圖去訪問一個不允許訪問的資源或檔案,或者以不當的方式進行訪問,如寫一個只讀檔案),非法指令(程式試圖去執行一個不存在的指令),特權指令錯(程式試圖執行一條只允許OS執行的指令),等待超時(程式等待謀事件的時間超過了規定的最大值),算術運算錯(程式試圖執行一個被禁止的運算,如被0除),I/O故障(I/O過程中發生了錯誤)。
③ 外界干預,程式應外界的請求而終止執行,如操作員或作業系統干預,父程式請求(父程式具有終止自己任何子孫程式的能力),父程式終止(父程式終止,其所有子孫程式也將終止)。
終止程式的步驟如下
① 根據被終止的程式的識別符號,從PCB集合彙總檢索除該程式的PCB,從中讀出該程式的狀態。
② 若被終止的程式正處於執行狀態,應立即終止該程式的執行,並置排程標誌位真,用於指示該程式被終止後應重新進行排程。
③ 若該程式還有子孫程式,還應將其子孫程式予以終止,以防他們成為不可控的程式。
④ 將被終止的程式所擁有的全部資源,或者歸還給其父程式,或者歸還給作業系統。
⑤ 將被終止的程式PCB從所在佇列或連結串列中移出,等待其他程式來蒐集資訊。
3.3 程式的阻塞與喚醒
引起程式阻塞與喚醒的事件如下
① 請求系統服務,當正在執行的程式請求作業系統提供服務時,由於某種原因,作業系統並不立即滿足該程式的要求,該程式只能轉變為阻塞狀態來等待。
② 啟動某種操作,當程式啟動某種操作後,如果該程式必須在該操作完成之後才能繼續執行,則必須先使該程式阻塞,以等待該操作完成。
③ 新資料尚未到達,對於相互合作的程式,如果其中一個程式需要先獲得另一合作程式提供的資料後才能對資料進行處理,則只要其所需資料尚未到達,該程式只有(等待)阻塞。
④ 無新工作可做,系統往往設定一些具有某些特定功能的系統程式,每當這種程式完成任務後,便把自己阻塞起來以等待新任務到來。
程式阻塞步驟如下
正在執行的程式發現上述某件事情時,由於無法繼續執行,於是程式便通過呼叫阻塞原語block把自己阻塞,可見,程式的阻塞是程式自身的一種主動行為,之後程式會停止執行,並將程式控制塊的狀態由執行改為阻塞,並將PCB插入阻塞佇列,如果系統中設定了因不同事件而阻塞的多個阻塞佇列,則應將本程式插入到具有相同事件的阻塞佇列中,最後,轉排程程式進行重新排程,將處理機分配給另一就緒程式並進行切換。即保留被阻塞程式的處理機狀態到PCB中,再按新程式的PCB中的處理機狀態設定CPU環境。
程式喚醒步驟如下
當被阻塞程式所期待的時間出現時,如I/O完成獲其所期待的資料已經到達,則由有關程式(如用完並釋放I/O裝置的程式)呼叫喚醒原語wakeup,將等待該事件的程式喚醒,首先將被阻塞的程式從等待該事件的阻塞佇列中移出,將其PCB中的現行狀態由阻塞改為就緒,然後再將該PCB插入到就緒佇列中。值得注意的是,block原語與wakeup原因應該在不同程式中執行。
3.4 程式的掛起與啟用
程式掛起步驟如下
當出現引起程式掛起的事件時,如使用者程式請求將自己掛起或父程式請求將自己的某個子程式掛起,系統將利用掛起原語suspend將指定程式或處於阻塞狀態的程式掛起。 檢查被掛起程式的狀態,若處於活動就緒狀態,便將其改為靜止就緒,對於活動阻塞狀態的程式,則將其改為靜止阻塞,若被掛起的狀態正在執行,則轉向排程程式重新排程。
程式啟用步驟如下
當發生啟用程式的事件時,例如,父程式或使用者程式請求啟用指定程式,若該程式駐在外存而記憶體中已有足夠的空間時,則可將在外存處於靜止就緒狀態的該程式換入記憶體,這時,利用啟用原語active將指定程式啟用,啟用原語先將程式從外存調入記憶體,檢查該程式的現行狀態,由對應的靜止狀態改為活動狀態,若使用搶佔式排程策略,則有新程式如就緒佇列時,應檢查是否要進行重新排程,即由排程程式將被啟用程式與當前程式進行優先順序的比較,如果被啟用程式的優先順序更低,就不必重新排程,否則,立即剝奪當前程式的執行,把處理機分配給剛被啟用的程式。
四、程式同步
程式同步主要是對多個相關程式在執行次序上進行協調,以使併發執行的諸程式之間能有效共享資源和相互合作,而從使程式的執行具有可再現性。在多道程式環境下,當程式併發執行時,由於資源共享和程式合作,使處於一個系統中的諸程式之間可能存在著以下兩種形式的制約關係。
① 間接相互制約關係,同處於一個系統中的程式,通常都共享著某種系統資源,如共享CPU、I/O裝置等,間接相互制約即源於這種資源共享。
② 直接相互制約關係,這種制約主要源於程式間的合作,如A程式通過緩衝向B程式提供資料,當緩衝為空時,B阻塞,待A輸入資料後,B被喚醒,緩衝滿時,A阻塞,待B取出資料後,A被喚醒。
4.1 臨界區
許多硬體資源如印表機,磁帶機等,都屬於臨界資源,諸程式應該採取互斥方式,實現對這種資源的共享。人們把在每個程式中訪問臨界資源的那段程式碼成為臨界區,顯然,若能保證諸程式互斥地進入自己的臨界區,便可實現諸程式對臨界資源的互斥訪問。
4.2 同步機制遵循的原則
① 空閒讓進,當無程式處於臨界區時,表明臨界資源處於空閒狀態,應允許一個請求進入臨界區的程式立即進入自己的臨界區,以有效的利用臨界資源。
② 忙則等待,當已有程式進入臨界區時,表明臨界資源正在被訪問,因而其他檢視進入臨界區的程式必須等待,以保證對臨界資源的互斥訪問。
③ 有限等待,對要求訪問臨界資源的程式 ,應保證在有限時限內能進入自己的臨界區,以免陷入死等狀態。
④ 讓權等待,當程式不能進入自己的臨界區時,應立即釋放處理機,以免程式陷入忙等狀態。
4.3 程式同步程式問題
1. 生產者/消費者問題
2. 哲學家進餐問題
3. 讀寫問題
五、程式通訊
程式通訊,是指程式之間的資訊交換,程式的互斥和同步,由於只能交換很少量的資訊而被歸結為低階通訊,目前的高階通訊機制可歸結為三大類
① 共享儲存器系統
相互通訊的程式共享某些資料結構或共享儲存區,程式之間能夠通過這些空間進行通訊,基於此,又可以分為如下兩種型別:基於共享資料結構的通訊方式,在這種通訊中,要求諸程式共用某些資料結構,藉此實現程式間的資訊交換。基於共享儲存區的通訊方式,為了傳輸大量資料,在儲存器中劃出一塊共享儲存區,諸程式可通過對共享儲存區中的資料的讀或寫來實現通訊。
② 訊息傳遞系統
程式間的資料交換是以格式化的訊息為單位,程式設計師直接利用作業系統提供的一組通訊命令(原語),不僅能實現大量資料的傳遞,而且還隱藏了通訊的實現細節,使通訊過程對使用者是透明的,從而大幅減少通訊程式編制的複雜性。
③ 管道通訊
連線一個讀程式和一個寫程式以實現它們之間通訊的一個共享檔案,又名pipe檔案,向管道(共享檔案)提供輸入的傳送程式,以字元流形式將大量的資料送入管道;而接受管道輸出的接受程式,則從管道中接受資料,由於傳送和接受程式是利用管道進行通訊的,因此叫做管道通訊。管道通訊需要具有三方面的協調能力:互斥(當一個程式正在對pipe執行讀/寫時,其他程式必須等待),同步(當寫程式把一定數量的資料寫入pipe,便去睡眠等待,到讀程式取走資料後,再把它喚醒,當讀程式讀一個空pipe時,也應該睡眠等待,直到有資料寫入管道,才將其喚醒),確定對方是否存在,只有確定了對方已存在時,才能進行通訊。
六、執行緒
6.1 執行緒與程式的比較
執行緒稱為輕型程式或程式元,在引入執行緒的作業系統,一個程式往往都擁有多個執行緒,至少有一個執行緒,下面從不同的方面將執行緒與程式進行比較(前提是作業系統引入了執行緒)。
① 排程
執行緒作為排程和分派的基本單位,而程式作為資源擁有的基本單位。同一程式中,執行緒的切換不會引起程式的切換,但從一個程式中的執行緒切換到另外一個程式中的執行緒時,將會引起程式切換。
② 併發性
不僅程式間可以併發執行,同一個程式中的多個執行緒之間亦可併發執行,是的作業系統具有更好的併發性,從而能更加有效地提高系統資源利用率和系統吞吐率。
③ 擁有資源
執行緒一般不擁有系統資源(除少量必不可少的資源),但它可以訪問其隸屬的程式的資源,即一個程式的程式碼段,資料段以及擁有的系統資源,如已開啟的檔案、I/O裝置等。
④ 系統開銷
在建立和撤銷程式時,系統都要為之建立和回收程式控制塊,分配或回收資源,作業系統付出的開銷明顯大於執行緒建立或撤銷時的開銷,在程式切換時,涉及到當前程式CPU環境的儲存和新被排程執行程式的CPU環境的設定,而執行緒的切換則僅需儲存和設定少量暫存器內容,不涉及儲存器管理方面的操作,所以執行緒的切換開銷遠小於程式切換開銷,以外,由於一個程式中的多個執行緒具有相同的地址空間,在同步和通訊的實現上也比較容易,在一些作業系統中,執行緒的切換,同步和通訊都無需作業系統核心的干預。
6.2 執行緒的屬性
① 輕型實體,每個執行緒都具有一個用於控制執行緒執行的執行緒控制塊TCB,用於指示被執行指令序列的程式計數器,保留區域性變數,少量狀態引數合返回地址等。
② 獨立排程和分派的基本單位,執行緒是能獨立執行的基本單位,切換非常迅速且開銷小。
③ 可併發執行,一個程式、不同程式的執行緒均可併發執行。
④ 共享程式資源,同一程式中的執行緒共享該程式所擁有的資源,所有執行緒擁有相同的地址空間(程式的地址空間),這意味著執行緒可以訪問該地址空間中的每一個虛地址,此外,還可以訪問程式所擁有的已開啟檔案,定時器,訊號量機構等。
6.3 執行緒的狀態
① 狀態引數,每一個執行緒可利用執行緒識別符號和一組狀態引數進行描述。狀態引數包括暫存器狀態(包括程式計數器和堆疊指標中的內容)、堆疊(儲存的區域性變數和返回地址)、執行緒執行狀態、優先順序、執行緒專有儲存器(儲存執行緒自己的具有變數拷貝)、訊號遮蔽(對某些資訊加以遮蔽)。
② 執行緒執行狀態,執行狀態包括執行狀態、就緒狀態、阻塞狀態。
6.4 執行緒的建立和終止
在建立新執行緒時,需要利用一個執行緒建立函式(或系統呼叫),並根據相應的引數,如指向執行緒主程式的入口指標、堆疊的大小、排程的優先順序等。線上程建立函式執行完後,將返回一個執行緒識別符號供以後使用。
終止執行緒的方式有兩種,執行緒完成工作後自願退出或者執行緒在執行中出現錯誤或由於某種原因而被其他執行緒強行終止。在大多數OS中,執行緒被終止後並不立即釋放它所佔有的資源,只有當程式中的其他執行緒執行了分離函式後,被終止的執行緒才與資源分離,此時的資源才能被其他執行緒利用。雖然已被終止但尚未釋放資源的執行緒,仍可以被需要它的執行緒所呼叫,以使被終止執行緒重新恢復執行。
6.5 多執行緒OS中的程式
① 作為系統資源分配的單位,任一程式中所擁有的資源包括受到分別保護的使用者地址空間、用於實現程式間和執行緒間同步和通訊的機制、已開啟的檔案和已申請到的I/O裝置,以及一張由核心程式維護的地址對映表,該表用於實現使用者程式的邏輯地址到記憶體地址的對映。
② 可包括多個執行緒,一個程式至少要有一個執行緒,有程式為執行緒提供資源及執行環境,使這些執行緒可併發執行。所有執行緒只能隸屬於某一個特定程式。
③ 程式不是一個可執行的實體,程式仍具有與執行相關的狀態,如執行狀態,表示程式中的某個執行緒正在執行,對程式所施加的與程式狀態有關的操作,也對其執行緒其作用,例如,把某個程式掛起時,該程式中的所有執行緒也都將被掛起,啟用某個程式時,屬於該程式的所有執行緒也都將被啟用。
6.6 執行緒間的同步和通訊
① 互斥鎖,互斥鎖是一種比較簡單的、用於實現執行緒間對資源互斥訪問的機制。由於操作互斥鎖的時間和空間開銷較低,因為較適合高頻度使用的關鍵共享資料和程式段。
② 條件變數,建立一個互斥鎖時便聯絡著一個條件變數,單純的互斥鎖用於短期鎖定,主要用來保證對臨界區的互斥進入,條件變數則用於執行緒的長期等待,直至所等待的資源成為可用的資源。
③ 訊號量機制,包括私有訊號量(同一程式的不同執行緒需要同步時,可呼叫建立訊號量的命令來建立私有訊號量,其資料結構存放在應用程式的地址空間中,私有訊號量屬於特定的程式所有,OS並不知道私有訊號量的存在,當發生私有訊號量的佔用者異常或正常結束,但並未釋放私有訊號量所佔有的空間的情況時,系統將無法使它恢復為0,也不能將它傳送到下一個請求它的執行緒),公用訊號量(其實現不同程式間或不同程式中各執行緒之間的同步而設定,由所有程式使用,其資料結構放在手保護的系統儲存區中,由OS為它分配空間並進行管理,也稱為系統訊號量,OS會自動回收其空間,其是一種比較安全的同步機制)
6.7 執行緒的實現方式
① 核心支援執行緒(Kernel Supported Threads)
無論使用者程式中的執行緒,還是系統程式中的執行緒,它們的建立、撤銷和切換等也是依靠核心,在核心空間中實現。核心空間為每個核心支援執行緒設定了一個執行緒控制塊,核心是根據該控制塊而感知某個執行緒的存在,並對其加以控制。其優點如下
1. 多處理機系統中,記憶體能夠同時排程同一個程式中多個執行緒並行執行。
2. 程式中一個執行緒被阻塞了,核心可以排程該程式中的其他執行緒,也可以執行其他程式中的執行緒。
3. 核心支援執行緒具有很小的資料結構和堆疊,執行緒切換快,開銷小。
4. 核心本身採用多執行緒技術,提高系統的執行速度和效率。
其缺點是對使用者的執行緒切換而言,切換開銷較大,因為需要進行模式的切換。
② 使用者級執行緒(User Level Thread)
使用者級執行緒僅存在於使用者空間中。對於執行緒的建立、撤銷、同步和通訊等,無需利用系統呼叫來實現,對於使用者級執行緒的切換,通常發生在一個應用程式的諸多執行緒之間。執行緒的任務控制塊都是設定在使用者空間,執行緒所執行的操作也無需核心的幫助,因而核心完全不知道使用者級執行緒的存在。設定了使用者級執行緒的系統,仍可以以程式為單位進行排程,而設定的是核心支援執行緒,則以執行緒為單位進行排程。其優點如下
1. 執行緒切換不需要轉換到核心空間,節省了切換開銷。
2. 排程演算法可以是程式專用的,程式可以選擇不同的排程演算法對自己的執行緒進行管理和排程,而與作業系統的低階排程演算法無關。
3. 使用者級執行緒的實現與作業系統平臺無關,在所有的應用程式中都可以對其進行共享。
其缺點如下
1. 系統呼叫的阻塞問題,當執行緒執行一個系統呼叫時,不僅該執行緒被阻塞,而且程式內的所有執行緒都會被阻塞,而在核心支援執行緒方式中,程式中的其他執行緒仍可以執行。
2. 在單純的使用者級執行緒實現方式中,多執行緒應用不能利用多處理機進行多處理的優點,核心每次分配給一個程式的僅有一個CPU,因此程式中僅有一個執行緒能執行,在該執行緒放棄CPU之前,其他執行緒只能等待。
③ 組合方式
核心支援多KST執行緒的建立、排程和管理,同時也允許使用者應用程式簡歷、排程和管理使用者級執行緒。
6.8 執行緒的實現
① 核心支援執行緒的實現
系統在建立一個新程式時,便為它分配一個任務資料區PTAD(Per Task Data Area),其中包括若干個執行緒控制塊TCB空間,其儲存在核心空間中。當程式要建立一個新執行緒時,便為其分配一個TCB,填入相關的資訊,分配必要的資源,於是新建立的執行緒便有機會執行。當PTAD中的所有TCB分配完後,程式又要建立新的執行緒時,只要其所建立的執行緒數量未超過系統的允許值是,系統可再為之分配新的TCB空間。在撤銷一個執行緒時,也回收該執行緒的所有資源和TCB,有的系統為了減少建立和撤銷一個執行緒時的開銷,在撤銷一個執行緒時,並不立即回收該執行緒的資源和TCB,當以後要建立一個新執行緒時,便可利用已被撤銷但仍保持有資源和TCB的執行緒作為新執行緒。
② 使用者級執行緒的實現
使用者級執行緒是在使用者空間實現的,所有的使用者級執行緒都具有相同的結構,他們都執行在一箇中間系統上面,當前有兩種方式實現中間系統,即執行時系統和核心控制執行緒。
執行時系統是用於管理和控制執行緒的函式(過程)的集合,其中包括用於建立和撤銷執行緒的函式、執行緒同步和通訊的函式以及實現執行緒排程的函式等,正因為有了這些函式,才使得使用者級執行緒與核心無關,執行時系統中的所有函式都駐留在使用者空間,並作為使用者級執行緒與核心之間的介面。使用者級執行緒在切換時不需要轉入核心態,而是由執行時系統中的執行緒切換過程來執行切換任務。
核心控制執行緒又稱為輕型程式LWP(Light Weight Process),每一個程式都可擁有多個LWP,同使用者級執行緒一樣,每個LWP都有自己的資料結構(如TCB),其中包括執行緒識別符號,優先順序,狀態、棧、區域性儲存區等。它們也可以享受程式所擁有的資源,LWP可通過系統呼叫來獲得核心提供的服務,當一個使用者級執行緒執行時,只要將它連線到一個LWP上,此時它便具有了核心提供支援執行緒的所有屬性,這種執行緒實現方式就是組合方式。LWP會做成一個緩衝池,使用者級執行緒都可以連線到任何一個LWP上,為了使每一使用者級執行緒都能利用LWP與核心通訊,可以使多個使用者級執行緒多路複用一個LWP,但只有當前連線到LWP上的執行緒才能與核心通訊,其餘程式或者阻塞,或者等待LWP,每一個LWP也需要連線到一個核心級執行緒上,這樣,通過LWP可把使用者級執行緒與核心執行緒連線起來,使用者級執行緒可通過LWP來訪問核心,核心看不到使用者級執行緒,LWP實現了核心與使用者級執行緒的隔離。
③ 使用者級執行緒與核心控制執行緒的連線
1. 一對一模型
為每一個使用者執行緒都設定一個核心控制執行緒與之連線,當一個執行緒阻塞時,允許排程另一個執行緒執行,在多處理機系統中,則有多個執行緒並行執行。
2. 多對一模型
將多個使用者執行緒對映到一個核心控制執行緒,為了管理方便,這些使用者執行緒一般屬於一個程式,執行在該程式的使用者空間,對這些執行緒的排程和管理也是在該程式的使用者空間完成的,當使用者執行緒需要訪問核心時,才將其對映到一個核心控制執行緒上,但每次只允許一個執行緒進行對映。 執行緒管理開銷小,效率高,但當一個執行緒在訪問核心時發生阻塞,則整個程式都會被阻塞,並且在多處理機系統中,一個程式的多個執行緒無法實現並行。
3. 多對多模型
將多個使用者執行緒對映到多個核心控制執行緒,核心控制執行緒的數目可以根據應用程式和系統的不同而變化。
七、總結
關於程式和執行緒的介紹就到這裡,程式和執行緒是作業系統裡面非常核心的概念,弄懂這些概念對於之後的學會會很有好處,謝謝各位園友的觀看~