幾種進程間的通信方式
管道( pipe ):
管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用。進程的親緣關系通常是指父子進程關系。
有名管道 (named pipe) :
有名管道也是半雙工的通信方式,但是它允許無親緣關系進程間的通信。
信號量( semophore ) :
信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
消息隊列( message queue ) :
消息隊列是由消息的鏈表,存放在內核中并由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩沖區大小受限等缺點。
信號 ( signal ) :
信號是一種比較復雜的通信方式,用于通知接收進程某個事件已經發生。
共享內存( shared memory ) :
共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號兩,配合使用,來實現進程間的同步和通信。
套接字( socket ) :
套接字也是一種進程間通信機制,與其他通信機制不同的是,它可用于不同主機的進程通信。
死鎖
死鎖是指兩個或兩個以上的進程在執行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處于死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。
產生條件
雖然進程在運行過程中,可能發生死鎖,但死鎖的發生也必須具備一定的條件,死鎖的發生必須具備以下四個[必要條件]
1****)互斥條件:指進程對所分配到的資源進行排它性使用,即在一段時間內某資源只由一個進程占用。如果此時還有其它進程請求資源,則請求者只能等待,直至占有資源的進程用畢釋放。
2****)請求和保持條件:指進程已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它進程占有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放。
3****)不剝奪條件:指進程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時由自己釋放。
4****)環路等待條件:指在發生死鎖時,必然存在一個進程——資源的環形鏈,即進程集合{P0,P1,P2,···,Pn}中的P0正在等待一個P1占用的資源;P1正在等待P2占用的資源,……,Pn正在等待已被P0占用的資源。
只要打破四個必要條件之一就能有效預防死鎖的發生:
①打破互斥條件:改造獨占性資源為虛擬資源,大部分資源已無法改造。
②打破不可搶占條件:當一進程占有一獨占性資源后又申請一獨占性資源而無法滿足,則退出原占有的資源。
③打破占有且申請條件:采用資源預先分配策略,即進程運行前申請全部資源,滿足則運行,不然就等待,這樣就不會占有且申請。
④打破循環等待條件:實現資源有序分配策略,對所有設備實現分類編號,所有進程只能采用按序號遞增的形式申請資源。即破壞了環路
銀行家算法(適用于每種資源類型有多個實例)
為了實現銀行家算法,必須要有幾個數據結構:
注:設n為系統進程的個數,m為在資源類型的種類。
Available:長度為m的向量。表示每種資源的現有實例的數量。如果Available[j]=k,那么資源Rj有k個實例有效。
Max:n * m矩陣。定義每種進程的最大需求。如果Max[i][j]=k,那么進程Pi可以最多請求資源Rj的k個實例。
Allocation:n * m矩陣。定義每個進程現在所分配的各種資源類型的實例數量。如果Allocation[I,j]=k,那么進程Pj當前分配了k個資源Rj的實例。
Need:n * m矩陣。表示每個進程還需要的剩余的資源。如果Need[i][j]=k,那么進程Pj還需要資源Rj的k個實例。
注:Need[i][j] = Max[i][j] – Allocation [i][j]
為了描述方便,我們采用一些簡化的表示方法:
設X和Y為長度為n的向量,則X <= Y當且僅當對所有i = 1,2,...,n,X[i] <= Y[i]。例如,如果X = (1,7,2,3)而Y = (0,3,2,1),那么Y <= X。如果Y <= X且Y != X,那么Y < X。
可以將Allocation和Need的每行作為向量,并分別用Allocation i和Need i來表示,向量Allocation i表示分配給進程Pi的資源;向量Need i表示進程為完成其任務可能仍然需要申請的額外資源。
銀行家算法可整體分成兩個部分:
1.安全性算法
確認計算機系統是否處于安全狀態的算法分為如下幾步:
(1)設Work和Finish分別為長度為m和n的向量。按如下方式進行初始化,Work = Avaliable且對于i = 0,1,...,n - 1,Finish[i] = false。
(2)查找這樣的i使其滿足
·Finish[i] = false
·Need i <= Work
如果沒有這樣的i,那么就轉到第(4)步。
(3)Work = Work + Allocation i
Finish[i] = true
返回第(2)步
(4)如果對所有i,Finish[i] = true,那么系統則處于安全狀態。
該算法可能需要m * n^2數量級的操作以確定系統是否處于安全狀態。
2.資源請求算法
現在,描述如何判斷是否可安全允許請求的算法。
設Request i為進程Pi的請求向量。如果Request i[j] == k,那么進程Pi需要資源類型Rj的實例數量為k。當進程Pi作出資源請求時,采取如下動作:
(1)如果Request i <= Need i,那么轉到第(2)步。否則,產生出錯條件,這是因為進程Pi已超過了其最大請求。
(2)如果Request i <= Available,那么轉到第(3)步。否則,Pi必須等待,這是因為沒有可用資源。
(3)假定系統可以分配給進程Pi所請求的資源,并按如下方式修改狀態:
Available = Available - Request i;
Allocation i = Allocation i + Request i;
Need i = Need i - Request i;
如果所產生的資源分配狀態是安全的(通過上面的安全性算法),那么Pi可分配到它所請求的資源。但是,如果新狀態不安全,則進程Pi必須等待Request i并恢復到原來的資源分配狀態。