154.進程的描述與控制

第二章 進程的描述與控制html

2.1  前趨圖和程序執行  

在早期未配置OS的系統和單道批處理系統中,程序的執行方式是順序執行,即在內存中僅裝入一道用戶程序,由它獨佔系統中的全部資源,只有在一個用戶程序執行完成後,才容許裝入另外一個程序並執行。可見,這種方式浪費資源、系統運行效率低等缺點。 程序員

 

2.1.1  前趨圖  

  爲了能更好地描述程序的順序和併發執行狀況,咱們先介紹用於描述程序執行前後順序的前趨圖。所謂前趨圖(Precedence Graph),是指一個有向無循環圖,可記爲DAG(Directed Acyclic Graph),它用於描述進程之間執行的前後順序。圖中的每一個結點可用來表示一個進程或程序段,乃至一條語句,結點間的有向邊則表示兩個結點之間存在的偏序(Partial Order)或前趨關係(Precedence Relation)。算法

  進程(或程序)之間的前趨關係可用「→」來表示,若是進程Pi和Pj存在着前趨關係,可表示爲(Pi,Pj)∈→,也可寫成Pi→Pj,表示在Pj開始執行以前Pi 必須完成。此時稱Pi是Pj的直接前趨,而稱Pj是Pi的直接後繼。在前趨圖中,把沒有前趨的結點稱爲初始結點(Initial Node),把沒有後繼的結點稱爲終止結點(Final Node)。此外,每一個結點還具備一個重量(Weight),用於表示該結點所含有的程序量或程序的執行 時間。 數據庫

  在圖2-1(a)所示的前趨圖中,存在着以下前趨關係:   P1→P2,P1→P3,P1→P4,P2→P5,P3→P5,P4→P6,P4→P7,P5→P8,P6→P8,P7→P9,P8→P9 或表示爲:  P={P1, P2, P3, P4, P5, P6, P7, P8, P9}    ={(P1, P2), (P1, P3), (P1, P4), (P2, P5), (P3, P5), (P4, P6), (P4, P7), (P5, P8), (P6, P8), (P7, P9), (P8, P9)}編程

  應當注意,前趨圖中是不容許有循環的,不然必然會產生不可能實現的前趨關係。如圖2-1(b)所示的前趨關係中就存在着循環。它一方面要求在S3開始執行以前,S2必須完成,另外一方面又要求在S2開始執行以前,S3必須完成。顯然,這種關係是不可能實現的。         數組

S2→S3,S3→S2安全

 

圖2-1 前趨圖服務器

 

2.1.2  程序順序執行 

1. 程序的順序執行 網絡

  一般,一個應用程序由若干個程序段組成,每個程序段完成特定的功能,它們在執行時,都須要按照某種前後次序順序執行,僅當前一程序段執行完後,才運行後一程序段。例如,在進行計算時,應先運行輸入程序,用於輸入用戶的程序和數據;而後運行計算程序,對所輸入的數據進行計算;最後纔是運行打印程序,打印計算結果。咱們用結點(Node)表明各程序段的操做(在圖2-1中用圓圈表示),其中I表明輸入操做,C表明計算操做,P爲打印操做,用箭頭指示操做的前後次序。數據結構

  這樣,上述的三個程序段間就存在着這樣的前趨關係:Ii→Ci→Pi,其執行的順序可用前趨圖2-2(a)描述。   即便是一個程序段,也可能存在着執行順序問題,下面示出了一個包含了三條語句的程序段:

  S1: a :=x+y;   S2: b :=a-5;   S3: c :=b+1;

  其中,語句S2必須在語句S1後(即a被賦值)才能執行,語句S3也只能在b被賦值後才能執行,所以,三條語句存在着這樣的前趨關係:S1→S2→S3,應按前趨圖2-2(b)所示的順序執行。

 

圖2-2 程序順序執行的前趨圖

 

2. 程序順序執行時的特徵

由上所述能夠得知,在程序順序執行時,具備這樣三個特徵:

① 順序性:指處理機嚴格地按照程序所規定的順序執行,即每一操做必須在下一個操做開始以前結束;

② 封閉性:指程序在封閉的環境下運行,即程序運行時獨佔全機資源,資源的狀態(除初始狀態外)只有本程序才能改變它,程序一旦開始執行,其執行結果不受外界因素影響;

③ 可再現性:指只要程序執行時的環境和初始條件相同,當程序重複執行時,不論它是從頭至尾不停頓地執行,仍是「停停走走」地執行,均可得到相同的結果。程序順序執行時的這種特性,爲程序員檢測和校訂程序的錯誤帶來了很大的方便。

 

 2.1.3 程序併發執行  

1. 程序的併發執行 

  咱們經過一個常見的例子來講明程序的順序執行和併發執行。在圖2-2中的輸入程序、計算程序和打印程序三者之間,存在着Ii→Ci→Pi這樣的前趨關係,以致對一個做業的輸入、計算和打印三個程序段必須順序執行。但如果對一批做業進行處理時,每道做業的輸入、計算和打印程序段的執行狀況如圖2-3所示。 

 

圖2-3 程序併發執行時的前趨圖

  由圖2-3能夠看出,存在前趨關係Ii→Ci,Ii→Ii+1,Ci→Pi,Ci→Ci+1,Pi→Pi+1,而Ii+1和Ci及Pi-1是重疊的,即在Pi-1和Ci以及Ii+1之間,不存在前趨關係,能夠併發執行。

  對於具備下述四條語句的程序段:

  S1: a :=x+2   S2: b :=y+4   S3: c :=a+b   S4: d :=c+b   

  可畫出圖2-4所示的前趨關係。能夠看出:S3必須在a和b被賦值後方能執行;S4必須在S3以後執行;但S1和S2則能夠併發執行,由於它們彼此互不依賴。

圖2-4 四條語句的前趨關係

 

2. 程序併發執行時的特徵

  在引入了程序間的併發執行功能後,雖然提升了系統的吞吐量和資源利用率,但因爲它們共享系統資源,以及它們爲完成同一項任務而相互合做,導致在這些併發執行的程序之間必將造成相互制約的關係,由此會給程序併發執行帶來新的特徵。

  (1) 間斷性。   (2) 失去封閉性。   (3) 不可再現性。

 

2.2  進 程 的 描 述 

2.2.1  進程的定義和特徵 

1. 進程的定義

      在多道程序環境下,程序的執行屬於併發執行,此時它們將失去其封閉性,並具備間斷性,以及其運行結果不可再現性的特徵。由此,決定了一般的程序是不能參與併發執行的,不然,程序的運行也就失去了意義。爲了能使程序併發執行,而且能夠對併發執行的程序加以描述和控制,人們引入了「進程」的概念。

 對於進程的定義,從不一樣的角度能夠有不一樣的定義,其中較典型的定義有:

  (1) 進程是程序的一次執行。

  (2) 進程是一個程序及其數據在處理機上順序執行時所發生的活動。

  (3) 進程是具備獨立功能的程序在一個數據集合上運行的過程,它是系統進行資源分配和調度的一個獨立單位。

2. 進程的特徵

進程和程序是兩個大相徑庭的概念,除了進程具備程序所沒有的PCB結構外,還具備下面一些特徵:   

(1) 動態性。   (2) 併發性。   (3) 獨立性。   (4) 異步性。

 

 2.2.2  進程的基本狀態及轉換  

1. 進程的三種基本狀態

因爲多個進程在併發執行時共享系統資源,導致它們在運行過程當中呈現間斷性的運行規律,因此進程在其生命週期內可能具備多種狀態。通常而言,每個進程至少應處於如下三種基本狀態之一:

(1) 就緒(Ready)狀態。   (2) 執行(Running)狀態。   (3) 阻塞(Block)狀態。 

 

 2. 三種基本狀態的轉換

進程在運行過程當中會常常發生狀態的轉換。例如,處於就緒狀態的進程,在調度程序爲之分配了處理機以後即可執行,相應地,其狀態就由就緒態轉變爲執行態;正在執行的進程(當前進程)若是因分配給它的時間片已完而被剝奪處理機暫停執行時,其狀態便由執行轉爲就緒;若是因發生某事件,導致當前進程的執行受阻(例如進程訪問某臨界資源,而該資源正被其它進程訪問時),使之沒法繼續執行,則該進程狀態將由執行轉變爲阻塞。圖2-5示出了進程的三種基本狀態,以及各狀態之間的轉換關係。

圖2-5 進程的三種基本狀態及其轉換

 

3. 建立狀態和終止狀態

1) 建立狀態

  如前所述,進程是由建立而產生。建立一個進程是個很複雜的過程,通常要經過多個步驟才能完成:如首先由進程申請一個空白PCB,並向PCB中填寫用於控制和管理進程的信息;而後爲該進程分配運行時所必須的資源;最後,把該進程轉入就緒狀態並插入就緒隊列之中。但若是進程所需的資源尚不能獲得知足,好比系統尚無足夠的內存使進程沒法裝入其中,此時建立工做還沒有完成,進程不能被調度運行,因而把此時進程所處的狀態稱爲建立狀態。

2) 終止狀態

  進程的終止也要經過兩個步驟:首先,是等待操做系統進行善後處理,最後將其PCB清零,並將PCB空間返還系統。當一個進程到達了天然結束點,或是出現了沒法克服的錯誤,或是被操做系統所終結,或是被其餘有終止權的進程所終結,它將進入終止狀態。進入終止態的進程之後不能再執行,但在操做系統中依然保留一個記錄,其中保存狀態碼和一些計時統計數據,供其餘進程收集。一旦其餘進程完成了對其信息的提取以後,操做系統將刪除該進程,即將其PCB清零,並將該空白PCB返還系統。圖2-6示出了增長了建立狀態和終止狀態後進程的五種狀態及轉換關係圖。

 

圖2-6 進程的五種基本狀態及轉換

 

2.2.3  掛起操做和進程狀態的轉換

1. 掛起操做的引入   

引入掛起操做的緣由,是基於系統和用戶的以下須要:   

(1) 終端用戶的須要。   (2) 父進程請求。   (3) 負荷調節的須要。   (4) 操做系統的須要。 

 

 2. 引入掛起原語操做後三個進程狀態的轉換

在引入掛起原語Suspend和激活原語Active後,在它們的做用下,進程將可能發生如下幾種狀態的轉換:   

(1) 活動就緒→靜止就緒。   

(2) 活動阻塞→靜止阻塞。   

(3) 靜止就緒→活動就緒。   

(4) 靜止阻塞→活動阻塞。

 

3. 引入掛起操做後五個進程狀態的轉換

  如圖2-8示出了增長了建立狀態和終止狀態後具備掛起狀態的進程狀態及轉換圖。

  如圖2-8所示,引進建立和終止狀態後,在進程狀態轉換時,與圖2-7所示的進程五狀態轉換相比較,要增長考慮下面的幾種狀況:

  (1)  NULL→建立:   (2) 建立→活動就緒:   (3) 建立→靜止就緒:   (4) 執行→終止:

 

圖2-7 具備掛起狀態的進程狀態圖

圖2-8 具備建立、終止和掛起狀態的進程狀態圖

 

2.2.4  進程管理中的數據結構

1. 操做系統中用於管理控制的數據結構    

在計算機系統中,對於每一個資源和每一個進程都設置了一個數據結構,用於表徵其實體,咱們稱之爲資源信息表或進程信息表,其中包含了資源或進程的標識、描述、狀態等信息以及一批指針。經過這些指針,能夠將同類資源或進程的信息表,或者同一進程所佔用的資源信息表分類連接成不一樣的隊列,便於操做系統進行查找。 

 如圖2-9所示,OS管理的這些數據結構通常分爲如下四類:內存表、設備表、文件表和用於進程管理的進程表,一般進程表又被稱爲進程控制塊PCB。 

 

 2. 進程控制塊PCB的做用

(1) 做爲獨立運行基本單位的標誌。

(2) 能實現間斷性運行方式。

(3) 提供進程管理所須要的信息。

(4) 提供進程調度所須要的信息。

(5) 實現與其它進程的同步與通訊。

 

 3. 進程控制塊中的信息 

在進程控制塊中,主要包括下述四個方面的信息。 

1) 進程標識符   

進程標識符用於惟一地標識一個進程。一個進程一般有兩種標識符:

  (1) 外部標識符。   (2) 內部標識符。

 2) 處理機狀態   

處理機狀態信息也稱爲處理機的上下文,主要是由處理機的各類寄存器中的內容組成的。 

 3) 進程調度信息   

在OS進行調度時,必須瞭解進程的狀態及有關進程調度的信息,這些信息包括:

① 進程狀態,指明進程的當前狀態,它是做爲進程調度和對換時的依據;

② 進程優先級,是用於描述進程使用處理機的優先級別的一個整數,優先級高的進程應優先得到處理機;

③ 進程調度所需的其它信息,它們與所採用的進程調度算法有關,好比,進程已等待CPU的時間總和、進程已執行的時間總和等;

④ 事件,是指進程由執行狀態轉變爲阻塞狀態所等待發生的事件,即阻塞緣由。

 4) 進程控制信息

是指用於進程控制所必須的信息,它包括:① 程序和數據的地址,進程實體中的程序和數據的內存或外存地(首)址,以便再調度到該進程執行時,能從PCB中找到其程序和數據;② 進程同步和通訊機制,這是實現進程同步和進程通訊時必需的機制,如消息隊列指針、信號量等,它們可能所有或部分地放在PCB中;③ 資源清單,在該清單中列出了進程在運行期間所需的所有資源(除CPU之外),另外還有一張已分配到該進程的資源的清單;④ 連接指針,它給出了本進程(PCB)所在隊列中的下一個進程的PCB的首地址。

 

4. 進程控制塊的組織方式

  在一個系統中,一般可擁有數十個、數百個乃至數千個PCB。爲了能對它們加以有效的管理,應該用適當的方式將這些PCB組織起來。目前經常使用的組織方式有如下三種。

(1) 線性方式,即將系統中全部的PCB都組織在一張線性表中,將該表的首址存放在內存的一個專用區域中。該方式實現簡單、開銷小,但每次查找時都須要掃描整張表,所以適合進程數目很少的系統。圖2-10示出了線性表的PCB組織方式。

 

 

圖2-10 PCB線性表示意圖

 

(2) 連接方式,即把具備相同狀態進程的PCB分別經過PCB中的連接字連接成一個隊列。這樣,能夠造成就緒隊列、若干個阻塞隊列和空白隊列等。對就緒隊列而言,每每按進程的優先級將PCB從高到低進行排列,將優先級高的進程PCB排在隊列的前面。一樣,也可把處於阻塞狀態進程的PCB根據其阻塞緣由的不一樣,排成多個阻塞隊列,如等待I/O操做完成的隊列和等待分配內存的隊列等。圖2-11示出了一種連接隊列的組織方式。

圖2-11 PCB連接隊列示意圖

 

(3) 索引方式,即系統根據全部進程狀態的不一樣,創建幾張索引表,例如,就緒索引表、阻塞索引表等,並把各索引表在內存的首地址記錄在內存的一些專用單元中。在每一個索引表的表目中,記錄具備相應狀態的某個PCB在PCB表中的地址。圖2-12示出了索引方式的PCB組織。

圖2-12 按索引方式組織PCB

 

2.3  進 程 控 制

進程控制是進程管理中最基本的功能,主要包括建立新進程、終止已完成的進程、將因發生異常狀況而沒法繼續運行的進程置於阻塞狀態、負責進程運行中的狀態轉換等功能。如當一個正在執行的進程因等待某事件而暫時不能繼續執行時,將其轉變爲阻塞狀態,而在該進程所期待的事件出現後,又將該進程轉換爲就緒狀態等。進程控制通常是由OS的內核中的原語來實現的。

 2.3.1  操做系統內核

  1. 支撐功能   (1) 中斷處理。   (2) 時鐘管理。   (3) 原語操做。

   2. 資源管理功能   (1) 進程管理。   (2) 存儲器管理。   (3) 設備管理。 

 

 2.3.2  進程的建立

1. 進程的層次結構

  在OS中,容許一個進程建立另外一個進程,一般把建立進程的進程稱爲父進程,而把被建立的進程稱爲子進程。子進程可繼續建立更多的孫進程,由此便造成了一個進程的層次結構。如在UNIX中,進程與其子孫進程共同組成一個進程家族(組)。

 

2. 進程圖

  爲了形象地描述一個進程的家族關係而引入了進程圖(Process Graph)。所謂進程圖就是用於描述進程間關係的一棵有向樹,如圖2-13所示。 

圖2-13 進程樹

 

3. 引發建立進程的事件

  爲使程序之間能併發運行,應先爲它們分別建立進程。致使一個進程去建立另外一個進程的典型事件有四類:

  (1) 用戶登陸。   (2) 做業調度。   (3) 提供服務。   (4) 應用請求。 

 

 4. 進程的建立(Creation of Process)

  在系統中每當出現了建立新進程的請求後,OS便調用進程建立原語Creat按下述步驟建立一個新進程:

  (1) 申請空白PCB,爲新進程申請得到惟一的數字標識符,並從PCB集合中索取一個空白PCB。

  (2) 爲新進程分配其運行所需的資源,包括各類物理和邏輯資源,如內存、文件、I/O設備和CPU時間等。

  (3) 初始化進程控制塊(PCB)。

  (4) 若是進程就緒隊列可以接納新進程,便將新進程插入就緒隊列。

 

 2.3.3  進程的終止

  1. 引發進程終止(Termination of Process)的事件

  (1) 正常結束   (2) 異常結束   (3) 外界干預 

 

  2. 進程的終止過程

  若是系統中發生了要求終止進程的某事件,OS便調用進程終止原語,按下述過程去終止指定的進程:

  (1) 根據被終止進程的標識符,從PCB集合中檢索出該進程的PCB,從中讀出該進程的狀態;

  (2) 若被終止進程正處於執行狀態,應當即終止該進程的執行,並置調度標誌爲真,用於指示該進程被終止後應從新進行調度;

  (3) 若該進程還有子孫進程,還應將其全部子孫進程也都予以終止,以防它們成爲不可控的進程;

  (4) 將被終止進程所擁有的所有資源或者歸還給其父進程,或者歸還給系統;

  (5) 將被終止進程(PCB)從所在隊列(或鏈表)中移出,等待其它程序來蒐集信息。

 

2.3.4  進程的阻塞與喚醒

  1. 引發進程阻塞和喚醒的事件

  有下述幾類事件會引發進程阻塞或被喚醒:

  (1) 向系統請求共享資源失敗。   (2) 等待某種操做的完成。   (3) 新數據還沒有到達。   (4) 等待新任務的到達。

 

   2. 進程阻塞過程

  正在執行的進程,若是發生了上述某事件,進程便經過調用阻塞原語block將本身阻塞。可見,阻塞是進程自身的一種主動行爲。進入block過程後,因爲該進程還處於執行狀態,因此應先當即中止執行,把進程控制塊中的現行狀態由「執行」改成阻塞,並將PCB插入阻塞隊列。若是系統中設置了因不一樣事件而阻塞的多個阻塞隊列,則應將本進程插入到具備相同事件的阻塞隊列。最後,轉調度程序進行從新調度,將處理機分配給另外一就緒進程,並進行切換,亦即,保留被阻塞進程的處理機狀態,按新進程的PCB中的處理機狀態設置CPU的環境。 

 

  3. 進程喚醒過程

  當被阻塞進程所期待的事件發生時,好比它所啓動的I/O操做已完成,或其所期待的數據已經到達,則由有關進程(好比提供數據的進程)調用喚醒原語wakeup,將等待該事件的進程喚醒。wakeup執行的過程是:首先把被阻塞的進程從等待該事件的阻塞隊列中移出,將其PCB中的現行狀態由阻塞改成就緒,而後再將該PCB插入到就緒隊列中。

 

2.3.5  進程的掛起與激活

  1. 進程的掛起   2. 進程的激活過程

 

 

 2.4 進 程 同 步

  在OS中引入進程後,一方面可使系統中的多道程序併發執行,這不只能有效地改善資源利用率,還可顯著地提升系統的吞吐量,但另外一方面卻使系統變得更加複雜。若是不能採起有效的措施,對多個進程的運行進行妥善的管理,必然會由於這些進程對系統資源的無序爭奪給系統形成混亂。導致每次處理的結果存在着不肯定性,即顯現出其不可再現性。

2.4.1 進程同步的基本概念

1. 兩種形式的制約關係

  1) 間接相互制約關係

  2) 直接相互制約關係

 

2. 臨界資源(Critical Resouce)

  在第一章中咱們曾經介紹過,許多硬件資源如打印機、 磁帶機等,都屬於臨界資源,諸進程間應採起互斥方式,實現對這種資源的共享。 

 

3. 臨界區(critical section)

  由前所述可知,不管是硬件臨界資源仍是軟件臨界資源,多個進程必須互斥地對它進行訪問。人們把在每一個進程中訪問臨界資源的那段代碼稱爲臨界區(critical section)。 

 

4. 同步機制應遵循的規則

  爲實現進程互斥地進入本身的臨界區,可用軟件方法,更多的是在系統中設置專門的同步機構來協調各進程間的運行。全部同步機制都應遵循下述四條準則:

  (1) 空閒讓進。   (2) 忙則等待。   (3) 有限等待。   (4) 讓權等待。

 

 2.4.2  硬件同步機制

  雖然能夠利用軟件方法解決諸進程互斥進入臨界區的問題,但有必定難度,而且存在很大的侷限性,於是如今已不多采用。相應地,目前許多計算機已提供了一些特殊的硬件指令,容許對一個字中的內容進行檢測和修正,或者是對兩個字的內容進行交換等。可利用這些特殊的指令來解決臨界區問題。

 

 1. 關中斷

  關中斷是實現互斥的最簡單的方法之一。在進入鎖測試以前關閉中斷,直到完成鎖測試並上鎖以後才能打開中斷。這樣,進程在臨界區執行期間,計算機系統不響應中斷,從而不會引起調度,也就不會發生進程或線程切換。由此,保證了對鎖的測試和關鎖操做的連續性和完整性,有效地保證了互斥。可是,關中斷的方法存在許多缺點:① 濫用關中斷權力可能致使嚴重後果;② 關中斷時間過長,會影響系統效率,限制了處理器交叉執行程序的能力;③ 關中斷方法也不適用於多CPU 系統,由於在一個處理器上關中斷並不能防止進程在其它處理器上執行相同的臨界段代碼。

 

2. 利用Test-and-Set指令實現互斥

  這是一種藉助一條硬件指令——「測試並創建」指令TS(Test-and-Set)以實現互斥的方法。在許多計算機中都提供了這種指令。 

 

3. 利用Swap指令實現進程互斥

  該指令稱爲對換指令,在Intel 80x86中又稱爲XCHG指令,用於交換兩個字的內容。 

 

 2.4.3 信號量機制

1. 整型信號量

  最初由Dijkstra把整型信號量定義爲一個用於表示資源數目的整型量S,它與通常整型量不一樣,除初始化外,僅能經過兩個標準的原子操做(Atomic Operation) wait(S)和signal(S)來訪問。很長時間以來,這兩個操做一直被分別稱爲P、V操做。 

 

2. 記錄型信號量

  在整型信號量機制中的wait操做,只要是信號量S≤0,就會不斷地測試。所以,該機制並未遵循「讓權等待」的準則,而是使進程處於「忙等」的狀態。記錄型信號量機制則是一種不存在「忙等」現象的進程同步機制。但在採起了「讓權等待」的策略後,又會出現多個進程等待訪問同一臨界資源的狀況。爲此,在信號量機制中,除了須要一個用於表明資源數目的整型變量value外,還應增長一個進程鏈表指針list,用於連接上述的全部等待進程。 

 

 3.  AND型信號量

  前面所述的進程互斥問題針對的是多個併發進程僅共享一個臨界資源的狀況。在有些應用場合,是一個進程每每須要得到兩個或更多的共享資源後方能執行其任務。假定現有兩個進程A和B,它們都要求訪問共享數據D和E,固然,共享數據都應做爲臨界資源。 

 

 4. 信號量集

  在前面所述的記錄型信號量機制中,wait(S)或signal(S)操做僅能對信號量施以加1或減1操做,意味着每次只能對某類臨界資源進行一個單位的申請或釋放。當一次須要N個單位時,便要進行N次wait(S)操做,這顯然是低效的,甚至會增長死鎖的機率。此外,在有些狀況下,爲確保系統的安全性,當所申請的資源數量低於某一下限值時,還必須進行管制,不予以分配。所以,當進程申請某類臨界資源時,在每次分配以前,都必須測試資源的數量,判斷是否大於可分配的下限值,決定是否予以分配。

 

 2.4.4 信號量的應用

1. 利用信號量實現進程互斥

爲使多個進程能互斥地訪問某臨界資源,只需爲該資源設置一互斥信號量mutex,並設其初始值爲1,而後將各進程訪問該資源的臨界區CS置於wait(mutex)和signal(mutex)操做之間便可。 

 

2. 利用信號量實現前趨關係

  還可利用信號量來描述程序或語句之間的前趨關係。設有兩個併發執行的進程P1和P2。P1中有語句S1;P2中有語句S2。咱們但願在S1執行後再執行S2。爲實現這種前趨關係,只需使進程P1和P2共享一個公用信號量S,並賦予其初值爲0,將signal(S)操做放在語句S1後面,而在S2語句前面插入wait(S)操做,即

  在進程P1中,用S1;signal(S);

  在進程P2中,用wait(S);S2;

因爲S被初始化爲0,這樣,若P2先執行一定阻塞,只有在進程P1執行完S1; signal(S);操做後使S增爲1時,P2進程方能成功執行語句S2。一樣,咱們能夠利用信號量按照語句間的前趨關係(見圖2-14),寫出一個更爲複雜的可併發執行的程序。 

 

圖2-14 前趨圖舉例

 

2.4.5 管程機制

1.管程的定義

  系統中的各類硬件資源和軟件資源都可用數據結構抽象地描述其資源特性,即用少許信息和對該資源所執行的操做來表徵該資源,而忽略它們的內部結構和實現細節。 

由上述的定義可知,管程由四部分組成:① 管程的名稱;② 局部於管程的共享數據結構說明;③ 對該數據結構進行操做的一組過程;④ 對局部於管程的共享數據設置初始值的語句。圖2-15是一個管程的示意圖。

 

圖2-15 管程的示意圖

 

2. 條件變量

  在利用管程實現進程同步時,必須設置同步工具,如兩個同步操做原語wait和signal。當某進程經過管程請求得到臨界資源而未能知足時,管程便調用wait原語使該進程等待,並將其排在等待隊列上,如圖2-13所示。僅當另外一進程訪問完成並釋放該資源以後,管程才又調用signal原語,喚醒等待隊列中的隊首進程。

 

 

 2.5 經典進程的同步問題

  在多道程序環境下,進程同步問題十分重要,也是至關有趣的問題,於是吸引了很多學者對它進行研究,由此而產生了一系列經典的進程同步問題,其中較有表明性的是「生產者—消費者」問題、「讀者—寫者問題」、「哲學家進餐問題」等等。經過對這些問題的研究和學習,能夠幫助咱們更好地理解進程同步的概念及實現方法。

 2.5.1 生產者-消費者問題

1. 利用記錄型信號量解決生產者-消費者問題

  假定在生產者和消費者之間的公用緩衝池中具備n個緩衝區,這時可利用互斥信號量mutex實現諸進程對緩衝池的互斥使用;利用信號量empty和full分別表示緩衝池中空緩衝區和滿緩衝區的數量。又假定這些生產者和消費者相互等效,只要緩衝池未滿,生產者即可將消息送入緩衝池;只要緩衝池未空,消費者即可從緩衝池中取走一個消息。 

2. 利用AND信號量解決生產者-消費者問題

  對於生產者-消費者問題,也可利用AND信號量來解決,即用Swait(empty,mutex)來代替wait(empty)和wait(mutex);用Ssignal(mutex,full)來代替signal(mutex)和signal(full);用Swait(full,mutex)代替wait(full)和wait(mutex),以及用Ssignal(mutex,empty)代替Signal(mutex)和Signal(empty)。 

3. 利用管程解決生產者-消費者問題

  在利用管程方法來解決生產者-消費者問題時,首先即是爲它們創建一個管程,並命名爲procducerconsumer,或簡稱爲PC。其中包括兩個過程:

  (1)  put(x)過程。   (2)  get(x)過程。 

 對於條件變量notfull和notempty,分別有兩個過程cwait和csignal對它們進行操做:

  (1)  cwait(condition)過程:當管程被一個進程佔用時,其餘進程調用該過程時阻塞,並掛在條件condition的隊列上。

  (2)  csignal(condition)過程:喚醒在cwait執行後阻塞在條件condition隊列上的進程,若是這樣的進程不止一個,則選擇其中一個實施喚醒操做;若是隊列爲空,則無操做而返回。

 

 2.5.2 哲學家進餐問題

  1. 利用記錄型信號量解決哲學家進餐問題

  經分析可知,放在桌子上的筷子是臨界資源,在一段時間內只容許一位哲學家使用。爲了實現對筷子的互斥使用,能夠用一個信號量表示一隻筷子,由這五個信號量構成信號量數組。 

 2. 利用AND信號量機制解決哲學家進餐問題

  在哲學家進餐問題中,要求每一個哲學家先得到兩個臨界資源(筷子)後方能進餐,這在本質上就是前面所介紹的AND同步問題,故用AND信號量機制可得到最簡潔的解法。

 

 2.5.3 讀者-寫者問題

1. 利用記錄型信號量解決讀者-寫者問題

  爲實現Reader與Writer進程間在讀或寫時的互斥而設置了一個互斥信號量Wmutex。另外,再設置一個整型變量Readcount表示正在讀的進程數目。因爲只要有一個Reader進程在讀,便不容許Writer進程去寫。所以,僅當Readcount=0,表示尚無Reader進程在讀時,Reader進程才須要執行Wait(Wmutex)操做。若wait(Wmutex)操做成功,Reader進程即可去讀,相應地,作Readcount+1操做。 

 2. 利用信號量集機制解決讀者-寫者問題

  這裏的讀者—寫者問題,與前面的略有不一樣,它增長了一個限制,即最多隻容許RN個讀者同時讀。爲此,又引入了一個信號量L,並賦予其初值爲RN,經過執行wait(L, 1, 1)操做來控制讀者的數目,每當有一個讀者進入時,就要先執行wait(L, 1, 1)操做,使L的值減1。當有RN個讀者進入讀後,L便減爲0,第RN + 1個讀者要進入讀時,必然會因wait(L, 1, 1)操做失敗而阻塞。 

 

 2.6  進 程 通 信

  進程通訊是指進程之間的信息交換。因爲進程的互斥與同步,須要在進程間交換必定的信息,故很多學者將它們也歸爲進程通訊,但只能把它們稱爲低級進程通訊。咱們以信號量機制爲例來講明,它們之因此低級的緣由在於:① 效率低,生產者每次只能向緩衝池投放一個產品(消息),消費者每次只能從緩衝區中取得一個消息;② 通訊對用戶不透明,OS只爲進程之間的通訊提供了共享存儲器。 

  在進程之間要傳送大量數據時,應當利用OS提供的高級通訊工具,該工具最主要的特色是:

  (1) 使用方便。OS隱藏了實現進程通訊的具體細節,向用戶提供了一組用於實現高級通訊的命令(原語),用戶可方便地直接利用它實現進程之間的通訊。或者說,通訊過程對用戶是透明的。這樣就大大減小了通訊程序編制上的複雜性。

  (2) 高效地傳送大量數據。用戶可直接利用高級通訊命令(原語)高效地傳送大量的數據。

 

 2.6.1 進程通訊的類型

1. 共享存儲器系統(Shared-Memory System)

  在共享存儲器系統中,相互通訊的進程共享某些數據結構或共享存儲區,進程之間可以經過這些空間進行通訊。據此,又可把它們分紅如下兩種類型:

  (1) 基於共享數據結構的通訊方式。   (2) 基於共享存儲區的通訊方式。

 

 2. 管道(pipe)通訊系統

  所謂「管道」,是指用於鏈接一個讀進程和一個寫進程以實現它們之間通訊的一個共享文件,又名pipe文件。向管道(共享文件)提供輸入的發送進程(即寫進程)以字符流形式將大量的數據送入管道;而接受管道輸出的接收進程(即讀進程)則從管道中接收(讀)數據。因爲發送進程和接收進程是利用管道進行通訊的,故又稱爲管道通訊。這種方式獨創於UNIX系統,因爲它能有效地傳送大量數據,於是又被引入到許多其它操做系統中。

 爲了協調雙方的通訊,管道機制必須提供如下三方面的協調能力:① 互斥,即當一個進程正在對pipe執行讀/寫操做時,其它(另外一)進程必須等待。② 同步,指當寫(輸入)進程把必定數量(如4 KB)的數據寫入pipe,便去睡眠等待,直到讀(輸出)進程取走數據後再把它喚醒。當讀進程讀一空pipe時,也應睡眠等待,直至寫進程將數據寫入管道後纔將之喚醒。③ 肯定對方是否存在,只有肯定了對方已存在時才能進行通訊。

 

3. 消息傳遞系統(Message passing system)

  在該機制中,進程沒必要藉助任何共享存儲區或數據結構,而是以格式化的消息 (message)爲單位,將通訊的數據封裝在消息中,並利用操做系統提供的一組通訊命令(原語),在進程間進行消息傳遞,完成進程間的數據交換。

  基於消息傳遞系統的通訊方式屬於高級通訊方式,因其實現方式的不一樣,可進一步分紅兩類:

  (1) 直接通訊方式   (2) 間接通訊方式 

 

4. 客戶機-服務器系統(Client-Server system)

1) 套接字(Socket)

  套接字起源於20世紀70年代加州大學伯克利分校版本的UNIX(即BSD Unix),是UNIX 操做系統下的網絡通訊接口。一開始,套接字被設計用在同一臺主機上多個應用程序之間的通訊(即進程間的通訊),主要是爲了解決多對進程同時通訊時端口和物理線路的多路複用問題。隨着計算機網絡技術的發展以及UNIX 操做系統的普遍使用,套接字已逐漸成爲最流行的網絡通訊程序接口之一。

2) 遠程過程調用和遠程方法調用

  遠程過程(函數)調用RPC(Remote Procedure Call),是一個通訊協議,用於經過網絡鏈接的系統。該協議容許運行於一臺主機(本地)系統上的進程調用另外一臺主機(遠程)系統上的進程,而對程序員表現爲常規的過程調用,無需額外地爲此編程。若是涉及的軟件採用面向對象編程,那麼遠程過程調用亦可稱作遠程方法調用。

  實際上,遠程過程調用的主要步驟是:

  (1) 本地過程調用者以通常方式調用遠程過程在本地關聯的客戶存根,傳遞相應的參數,而後將控制權轉移給客戶存根;

  (2) 客戶存根執行,完成包括過程名和調用參數等信息的消息創建,將控制權轉移給本地客戶進程;

  (3) 本地客戶進程完成與服務器的消息傳遞,將消息發送到遠程服務器進程;

  (4) 遠程服務器進程接收消息後轉入執行,並根據其中的遠程過程名找到對應的服務器存根,將消息轉給該存根;

  (5) 該服務器存根接到消息後,由阻塞狀態轉入執行狀態,拆開消息從中取出過程調用的參數,而後以通常方式調用服務器上關聯的過程;

  (6) 在服務器端的遠程過程運行完畢後,將結果返回給與之關聯的服務器存根;

  (7) 該服務器存根得到控制權運行,將結果打包爲消息,並將控制權轉移給遠程服務器進程;

  (8) 遠程服務器進程將消息發送回客戶端;

  (9) 本地客戶進程接收到消息後,根據其中的過程名將消息存入關聯的客戶存根,再將控制權轉移給客戶存根;

  (10) 客戶存根從消息中取出結果,返回給本地調用者進程,並完成控制權的轉移。

 

2.6.2 消息傳遞通訊的實現方式

1. 直接消息傳遞系統

  在直接消息傳遞系統中採用直接通訊方式,即發送進程利用OS所提供的發送命令(原語),直接把消息發送給目標進程。

1) 直接通訊原語

  (1) 對稱尋址方式。   (2) 非對稱尋址方式。

2) 消息的格式

  在消息傳遞系統中所傳遞的消息,必須具備必定的消息格式。在單機系統環境中,因爲發送進程和接收進程處於同一臺機器中,有着相同的環境,因此消息的格式比較簡單,可採用比較短的定長消息格式,以減小對消息的處理和存儲開銷。該方式可用於辦公自動化系統中,爲用戶提供快速的便箋式通訊。但這種方式對於須要發送較長消息的用戶是不方便的。爲此,可採用變長的消息格式,即進程所發送消息的長度是可變的。對於變長消息,系統不管在處理方面仍是存儲方面,均可能會付出更多的開銷,但其優勢在於方便了用戶。

3) 進程的同步方式

  在進程之間進行通訊時,一樣須要有進程同步機制,以使諸進程間能協調通訊。不管是發送進程仍是接收進程,在完成消息的發送或接收後,都存在兩種可能性,即進程或者繼續發送(或接收)或者阻塞。 

4) 通訊鏈路

  爲使在發送進程和接收進程之間能進行通訊,必須在二者之間創建一條通訊鏈路。有兩種方式創建通訊鏈路。第一種方式是:由發送進程在通訊以前用顯式的「創建鏈接」命令(原語)請求系統爲之創建一條通訊鏈路,在鏈路使用完後拆除鏈路。 

 

2. 信箱通訊

  1) 信箱的結構

  信箱定義爲一種數據結構。在邏輯上,能夠將其分爲兩個部分:

  (1) 信箱頭   (2) 信箱體

圖2-16 雙向信箱示意圖

2) 信箱通訊原語

  系統爲郵箱通訊提供了若干條原語,分別用於:

  (1) 郵箱的建立和撤消。   (2) 消息的發送和接收。

 3) 信箱的類型

  郵箱可由操做系統建立,也可由用戶進程建立,建立者是郵箱的擁有者。據此,可把郵箱分爲如下三類:

  (1) 私用郵箱。   (2) 公用郵箱。   (3) 共享郵箱。 

 

 

 2.6.3 直接消息傳遞系統實例

  消息緩衝隊列通訊機制首先由美國的Hansan提出,並在RC 4000系統上實現,後來被普遍應用於本地進程之間的通訊中。在這種通訊機制中,發送進程利用Send原語將消息直接發送給接收進程;接收進程則利用Receive原語接收消息。

 1. 消息緩衝隊列通訊機制中的數據結構

  (1) 消息緩衝區。   (2) PCB中有關通訊的數據項。

 

 2. 發送原語

  發送進程在利用發送原語發送消息以前,應先在本身的內存空間設置一發送區a,如圖2-17所示,把待發送的消息正文、發送進程標識符、消息長度等信息填入其中,而後調用發送原語,把消息發送給目標(接收)進程。發送原語首先根據發送區a中所設置的消息長度a.size來申請一緩衝區i,接着,把發送區a中的信息複製到緩衝區i中。爲了能將i掛在接收進程的消息隊列mq上,應先得到接收進程的內部標識符j,而後將i掛在j.mq上。因爲該隊列屬於臨界資源,故在執行insert操做的先後都要執行wait和signal操做。 

圖2-17 消息緩衝通訊

 

3. 接收原語

  接收進程調用接收原語receive(b),從本身的消息緩衝隊列mq中摘下第一個消息緩衝區i,並將其中的數據複製到以b爲首址的指定消息接收區內。 

 

 

 2.7  線程(Threads)的基本概念

2.7.1  線程的引入

  若是說,在OS中引入進程的目的是爲了使多個程序能併發執行,以提升資源利用率和系統吞吐量,那麼,在操做系統中再引入線程,則是爲了減小程序在併發執行時所付出的時空開銷,使OS具備更好的併發性。

 

 1. 進程的兩個基本屬性

  首先讓咱們來回顧進程的兩個基本屬性:

  ① 進程是一個可擁有資源的獨立單位,一個進程要能獨立運行,它必須擁有必定的資源,包括用於存放程序正文、數據的磁盤和內存地址空間,以及它在運行時所須要的I/O設備、已打開的文件、信號量等;

   ② 進程同時又是一個可獨立調度和分派的基本單位,一個進程要能獨立運行,它還必須是一個可獨立調度和分派的基本單位。每一個進程在系統中有惟一的PCB,系統可根據其PCB感知進程的存在,也能夠根據其PCB中的信息,對進程進行調度,還可將斷點信息保存在其PCB中。反之,再利用進程PCB中的信息來恢復進程運行的現場。正是因爲進程有這兩個基本屬性,才使進程成爲一個能獨立運行的基本單位,從而也就構成了進程併發執行的基礎。

 

 2. 程序併發執行所需付出的時空開銷

  爲使程序能併發執行,系統必須進行如下的一系列操做:

  (1) 建立進程,系統在建立一個進程時,必須爲它分配其所必需的、除處理機之外的全部資源,如內存空間、I/O設備,以及創建相應的PCB;

  (2) 撤消進程,系統在撤消進程時,又必須先對其所佔有的資源執行回收操做,而後再撤消PCB;

  (3) 進程切換,對進程進行上下文切換時,須要保留當前進程的CPU環境,設置新選中進程的CPU環境,於是須花費很多的處理機時間。

 

 3. 線程——做爲調度和分派的基本單位

  如何能使多個程序更好地併發執行,同時又儘可能減小系統的開銷,已成爲近年來設計操做系統時所追求的重要目標。有很多研究操做系統的學者們想到,要設法將進程的上述兩個屬性分開,由OS分開處理,亦即並不把做爲調度和分派的基本單位也同時做爲擁有資源的單位,以作到「輕裝上陣」;而對於擁有資源的基本單位,又不對之施以頻繁的切換。正是在這種思想的指導下,造成了線程的概念。

 

 

 2.7.2  線程與進程的比較

  1. 調度的基本單位   2. 併發性   3. 擁有資源   4. 獨立性   5. 系統開銷   6. 支持多處理機系統

 

  1 進程與線程的一個簡單解釋
  2 進程(process)和線程(thread)是操做系統的基本概念,可是它們比較抽象,不容易掌握。
  3 
  4 最近,我讀到一篇材料,發現有一個很好的類比,能夠把它們解釋地清晰易懂。
  5 
  6 1.
  7 
  8 
  9 
 10 計算機的核心是CPU,它承擔了全部的計算任務。它就像一座工廠,時刻在運行。
 11 
 12 2.
 13 
 14 
 15 
 16 假定工廠的電力有限,一次只能供給一個車間使用。也就是說,一個車間開工的時候,其餘車間都必須停工。背後的含義就是,單個CPU一次只能運行一個任務。
 17 
 18 3.
 19 
 20 
 21 
 22 進程就比如工廠的車間,它表明CPU所能處理的單個任務。任一時刻,CPU老是運行一個進程,其餘進程處於非運行狀態。
 23 
 24 4.
 25 
 26 
 27 
 28 一個車間裏,能夠有不少工人。他們協同完成一個任務。
 29 
 30 5.
 31 
 32 
 33 
 34 線程就比如車間裏的工人。一個進程能夠包括多個線程。
 35 
 36 6.
 37 
 38 
 39 
 40 車間的空間是工人們共享的,好比許多房間是每一個工人均可以進出的。這象徵一個進程的內存空間是共享的,每一個線程均可以使用這些共享內存。
 41 
 42 7.
 43 
 44 
 45 
 46 但是,每間房間的大小不一樣,有些房間最多隻能容納一我的,好比廁所。裏面有人的時候,其餘人就不能進去了。這表明一個線程使用某些共享內存時,其餘線程必須等它結束,才能使用這一塊內存。
 47 
 48 8.
 49 
 50 
 51 
 52 一個防止他人進入的簡單方法,就是門口加一把鎖。先到的人鎖上門,後到的人看到上鎖,就在門口排隊,等鎖打開再進去。這就叫"互斥鎖"(Mutual exclusion,縮寫 Mutex),防止多個線程同時讀寫某一塊內存區域。
 53 
 54 9.
 55 
 56 
 57 
 58 還有些房間,能夠同時容納n我的,好比廚房。也就是說,若是人數大於n,多出來的人只能在外面等着。這比如某些內存區域,只能供給固定數目的線程使用。
 59 
 60 10.
 61 
 62 
 63 
 64 這時的解決方法,就是在門口掛n把鑰匙。進去的人就取一把鑰匙,出來時再把鑰匙掛回原處。後到的人發現鑰匙架空了,就知道必須在門口排隊等着了。這種作法叫作"信號量"(Semaphore),用來保證多個線程不會互相沖突。
 65 
 66 不難看出,mutex是semaphore的一種特殊狀況(n=1時)。也就是說,徹底能夠用後者替代前者。可是,由於mutex較爲簡單,且效率高,因此在必須保證資源獨佔的狀況下,仍是採用這種設計。
 67 
 68 11.
 69 
 70 
 71 
 72 操做系統的設計,所以能夠歸結爲三點:
 73 
 74 (1)以多進程形式,容許多個任務同時運行;
 75 
 76 (2)以多線程形式,容許單個任務分紅不一樣的部分運行;
 77 
 78 (3)提供協調機制,一方面防止進程之間和線程之間產生衝突,另外一方面容許進程之間和線程之間共享資源。
 79 
 80 (完)
 81 
 82 轉:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
 83 
 84  
 85 
 86 這裏有一段知乎上的解釋:
 87 
 88 看見上面幾位的回答我真的是醉了。說幾句個人理解。
 89 
 90 首先來一句歸納的總論:進程和線程都是一個時間段的描述,是CPU工做時間段的描述。
 91 
 92 下面細說背景:
 93 CPU+RAM+各類資源(好比顯卡,光驅,鍵盤,GPS, 等等外設)構成咱們的電腦,可是電腦的運行,實際就是CPU和相關寄存器以及RAM之間的事情。
 94 
 95 一個最最基礎的事實:CPU太快,太快,太快了,寄存器僅僅可以追的上他的腳步,RAM和別的掛在各總線上的設備徹底是望其項背。那當多個任務要執行的時候怎麼辦呢?輪流着來?或者誰優先級高誰來?無論怎麼樣的策略,一句話就是在CPU看來就是輪流着來。
 96 
 97 一個必須知道的事實:執行一段程序代碼,實現一個功能的過程介紹 ,當獲得CPU的時候,相關的資源必須也已經就位,就是顯卡啊,GPS啊什麼的必須就位,而後CPU開始執行。這裏除了CPU之外全部的就構成了這個程序的執行環境,也就是咱們所定義的程序上下文。當這個程序執行完了,或者分配給他的CPU執行時間用完了,那它就要被切換出去,等待下一次CPU的臨幸。在被切換出去的最後一步工做就是保存程序上下文,由於這個是下次他被CPU臨幸的運行環境,必須保存。
 98 
 99 串聯起來的事實:前面講過在CPU看來全部的任務都是一個一個的輪流執行的,具體的輪流方法就是:先加載程序A的上下文,而後開始執行A,保存程序A的上下文,調入下一個要執行的程序B的程序上下文,而後開始執行B,保存程序B的上下文。。。。
100 
101 ========= 重要的東西出現了========
102 進程和線程就是這樣的背景出來的,兩個名詞不過是對應的CPU時間段的描述,名詞就是這樣的功能。
103 進程就是包換上下文切換的程序執行時間總和 = CPU加載上下文+CPU執行+CPU保存上下文
104 線程是什麼呢?
105 進程的顆粒度太大,每次都要有上下的調入,保存,調出。若是咱們把進程比喻爲一個運行在電腦上的軟件,那麼一個軟件的執行不多是一條邏輯執行的,一定有多個分支和多個程序段,就比如要實現程序A,實際分紅 a,b,c等多個塊組合而成。那麼這裏具體的執行就可能變成:
106 
107 程序A獲得CPU =》CPU加載上下文,開始執行程序A的a小段,而後執行A的b小段,而後再執行A的c小段,最後CPU保存A的上下文。
108 
109 這裏a,b,c的執行是共享了A的上下文,CPU在執行的時候沒有進行上下文切換的。這裏的a,b,c就是線程,也就是說線程是共享了進程的上下文環境,的更爲細小的CPU時間段。
110 
111 到此全文結束,再一個總結:
112 
113 進程和線程都是一個時間段的描述,是CPU工做時間段的描述,不過是顆粒大小不一樣。
114  
115 來自 https://www.zhihu.com/question/25532384
116 好文要頂 關注我 收藏該文    
線程和進程

 

 

 2.7.3  線程的狀態和線程控制塊

1. 線程運行的三個狀態   

  與傳統的進程同樣,在各線程之間也存在着共享資源和相互合做的制約關係,導致線程在運行時也具備間斷性。相應地,線程在運行時也具備下述三種基本狀態:

  (1) 執行狀態,表示線程已得到處理機而正在運行;

  (2) 就緒狀態,指線程已具有了各類執行條件,只須再得到CPU即可當即執行;

  (3) 阻塞狀態,指線程在執行中因某事件受阻而處於暫停狀態,例如,當一個線程執行從鍵盤讀入數據的系統調用時,該線程就被阻塞。

 

 2. 線程控制塊TCB

  如同每一個進程有一個進程控制塊同樣,系統也爲每一個線程配置了一個線程控制塊TCB,將全部用於控制和管理線程的信息記錄在線程控制塊中。

 

 3. 多線程OS中的進程屬性     

  一般在多線程OS中的進程都包含了多個線程,併爲它們提供資源。OS支持在一個進程中的多個線程能併發執行,但此時的進程就再也不做爲一個執行的實體。多線程OS中的進程有如下屬性:

  (1) 進程是一個可擁有資源的基本單位。   (2) 多個線程可併發執行。   (3) 進程已不是可執行的實體。

 

 2.8  線 程 的 實 現

2.8.1  線程的實現方式

  線程已在許多系統中實現,但各系統的實現方式並不徹底相同。在有的系統中,特別是一些數據庫管理系統,如infomix所實現的是用戶級線程; 而另外一些系統(如Macintosh和OS/2操做系統)所實現的是內核支持線程;還有一些系統如Solaris操做系統,則同時實現了這兩種類型的線程。

 

1. 內核支持線程KST(Kernel Supported Threads)

  在OS中的全部進程,不管是系統進程仍是用戶進程,都是在操做系統內核的支持下運行的,是與內核緊密相關的。而內核支持線程KST一樣也是在內核的支持下運行的,它們的建立、阻塞、撤消和切換等,也都是在內核空間實現的。爲了對內核線程進行控制和管理,在內核空間也爲每個內核線程設置了一個線程控制塊,內核根據該控制塊而感知某線程的存在,並對其加以控制。當前大多數OS都支持內核支持線程。

這種線程實現方式主要有四個主要優勢:

  (1) 在多處理器系統中,內核可以同時調度同一進程中的多個線程並行執行;

  (2) 若是進程中的一個線程被阻塞了,內核能夠調度該進程中的其它線程佔有處理器運行,也能夠運行其它進程中的線程;

  (3) 內核支持線程具備很小的數據結構和堆棧,線程的切換比較快,切換開銷小;

  (4) 內核自己也能夠採用多線程技術,能夠提升系統的執行速度和效率。

 

 2. 用戶級線程ULT(User Level Threads)

  用戶級線程是在用戶空間中實現的。對線程的建立、 撤消、同步與通訊等功能,都無需內核的支持,即用戶級線程是與內核無關的。在一個系統中的用戶級線程的數目能夠達到數百個至數千個。因爲這些線程的任務控制塊都是設置在用戶空間,而線程所執行的操做也無需內核的幫助,於是內核徹底不知道用戶級線程的存在。

 使用用戶級線程方式有許多優勢:

  (1) 線程切換不須要轉換到內核空間。

  (2) 調度算法能夠是進程專用的。

  (3) 用戶級線程的實現與OS平臺無關,由於對於線程管理的代碼是屬於用戶程序的一部分,全部的應用程序均可以對之進行共享。 

而用戶級線程方式的主要缺點則在於:

  (1) 系統調用的阻塞問題。在基於進程機制的OS中,大多數系統調用將使進程阻塞,所以,當線程執行一個系統調用時,不只該線程被阻塞,並且,進程內的全部線程會被阻塞。而在內核支持線程方式中,則進程中的其它線程仍然能夠運行。

  (2) 在單純的用戶級線程實現方式中,多線程應用不能利用多處理機進行多重處理的優勢,內核每次分配給一個進程的僅有一個CPU,所以,進程中僅有一個線程能執行,在該線程放棄CPU以前,其它線程只能等待。

 

 3. 組合方式

  有些OS把用戶級線程和內核支持線程兩種方式進行組合,提供了組合方式ULT/KST 線程。在組合方式線程系統中,內核支持多個內核支持線程的創建、調度和管理,同時,也容許用戶應用程序創建、調度和管理用戶級線程。 

 

圖2-18  多線程模型

 

2.8.2  線程的實現

1. 內核支持線程的實現

  在僅設置了內核支持線程的OS中,一種可能的線程控制方法是,系統在建立一個新進程時,便爲它分配一個任務數據區PTDA(Per Task Data Area),其中包括若干個線程控制塊TCB空間,如圖2-19所示。 

 

圖2-19 任務數據區空間

 

2. 用戶級線程的實現

  1) 運行時系統(Runtime System)

  所謂「運行時系統」,實質上是用於管理和控制線程的函數(過程)的集合,其中包括用於建立和撤消線程的函數、線程同步和通訊的函數,以及實現線程調度的函數等。正由於有這些函數,才能使用戶級線程與內核無關。運行時系統中的全部函數都駐留在用戶空間,並做爲用戶級線程與內核之間的接口。

   2) 內核控制線程

  這種線程又稱爲輕型進程LWP(Light Weight Process)。每個進程均可擁有多個LWP,同用戶級線程同樣,每一個LWP都有本身的數據結構(如TCB),其中包括線程標識符、優先級、狀態,另外還有棧和局部存儲區等。LWP也能夠共享進程所擁有的資源。LWP可經過系統調用來得到內核提供的服務,這樣,當一個用戶級線程運行時,只須將它鏈接到一個LWP上,此時它便具備了內核支持線程的全部屬性。這種線程實現方式就是組合方式。

圖2-20 利用輕型進程做爲中間系統

 

 2.8.3  線程的建立和終止

1. 線程的建立

  應用程序在啓動時,一般僅有一個線程在執行,人們把線程稱爲「初始化線程」,它的主要功能是用於建立新線程。在建立新線程時,須要利用一個線程建立函數(或系統調用),並提供相應的參數,如指向線程主程序的入口指針、堆棧的大小,以及用於調度的優先級等。在線程的建立函數執行完後,將返回一個線程標識符供之後使用。

 2. 線程的終止

  當一個線程完成了本身的任務(工做)後,或是線程在運行中出現異常狀況而須被強行終止時,由終止線程經過調用相應的函數(或系統調用)對它執行終止操做。但有些線程(主要是系統線程),它們一旦被創建起來以後,便一直運行下去而不被終止。在大多數的OS中,線程被停止後並不當即釋放它所佔有的資源,只有當進程中的其它線程執行了分離函數後,被終止的線程才與資源分離,此時的資源才能被其它線程利用。

 

習    題 

  1. 什麼是前趨圖? 爲何要引入前趨圖?

  2. 試畫出下面四條語句的前趨圖:

    S1: a = x+y;

    S2: b = z+1;

    S3: c = a-b;

    S4: w = c+1;

  3. 爲何程序併發執行會產生間斷性特徵?

  4. 程序併發執行時爲何會失去封閉性和可再現性? 

    5. 在操做系統中爲何要引入進程的概念? 它會產生什麼樣的影響?

  6. 試從動態性、併發性和獨立性上比較進程和程序。

  7. 試說明PCB的做用具體表如今哪幾個方面,爲何說PCB是進程存在的惟一標誌?

  8.  PCB提供了進程管理和進程調度所須要的哪些信息?

  9. 進程控制塊的組織方式有哪幾種?

  10. 何謂操做系統內核? 內核的主要功能是什麼?

  11. 試說明進程在三個基本狀態之間轉換的典型緣由。

  12. 爲何要引入掛起狀態? 該狀態有哪些性質?13. 在進行進程切換時,所要保存的處理機狀態信息有哪些?

  14. 試說明引發進程建立的主要事件。

  15. 試說明引發進程被撤消的主要事件。

  16. 在建立一個進程時所要完成的主要工做是什麼?

  17. 在撤消一個進程時所要完成的主要工做是什麼?

  18. 試說明引發進程阻塞或被喚醒的主要事件是什麼?

  19. 爲何要在OS中引入線程?

  20. 試說明線程具備哪些屬性?

   21. 試從調度性、併發性、擁有資源及系統開銷方面對進程和線程進行比較。

  22. 線程控制塊TCB中包含了哪些內容?

  23. 何謂用戶級線程和內核支持線程?

  24. 試說明用戶級線程的實現方法。

  25. 試說明內核支持線程的實現方法。

  26. 多線程模型有哪幾種類型? 多對一模型有何優缺點? 

 

 

線程:http://www.javashuo.com/article/p-wiueyzzz-hc.html

 

 

 

 

相關文章
相關標籤/搜索