操作系統-處理機調度與死鎖3(死鎖)
7.死鎖問題
死鎖是指多個進程等待其它進程佔有的資源,因而無限期等待下去的局面。
系統發生死鎖時,一定具備以下四個條件:
- 互斥條件。對於一個排他性資源,某一時刻最多允許一個進程佔有。
- 佔有且申請條件。進程至少已佔有一個資源,又要申請新的資源。此時該進程阻塞,且在等待過程中不釋放已經佔有的資源。
- 不可搶佔條件。進程獲得的資源在未使用之前,其他進程不得搶佔該資源。
- 環路條件。若干個進程相互要佔有彼此的資源,形成一個環路。
8.死鎖的避免
要避免死鎖,分為靜態策略和動態策略。靜態策略主要是實現避免形成四個必要條件。而動態策略則是為進程安排一個安全的推進順序,而不限制限制進程使用資源的命令。在進程申請資源時,系統需要計算資源分配的安全性,若此次分配不會導致死鎖,則將資源分配給進程。
9.用銀行家算法避免死鎖
9.1 銀行家算法的數據結構
- 可利用的資源向量Available
可利用資源向量是一個含有m個元素的數組,若Available[j] = K,表示系統中第\(R_j\)類資源還有K個。
- 最大需求矩陣Max
最大需求矩陣Max是一個\(n\times m\)的矩陣,它定義了系統的n個進程對於m類資源的最大需求。
- 分配矩陣Allocation
分配矩陣也是一個\(n\times m\)的矩陣,它定義了系統中每一進程已佔有的每一類資源數。
- 需求矩陣Need
Need矩陣表示系統中n類進程對於m類資源需要的數量。
9.2 銀行家算法的實現
- 進程申請資源的情況
設\(Requests_i\)是進程\(P_i\)的請求向量,根據\(Requests_i[i]與Need[i]\)的關係,可以分為以下三種情況:進程資源需求超過系統最大值出錯、進程一次性對其所需的資源全部申請完成、進程申請部分資源。
- 銀行家算法的描述
進程\(P_i\)發出資源請求,系統請求的步驟為:
- 如果\(Requests_i[i] \leq Need[i]\),便轉向步驟b,否則顯示出錯。
- 如果\(Requests_i[i] \leq Available\),便轉向步驟c,否則表示暫無足夠資源,進程需等待。
- 假設系統將資源分配給P,則需修改數據結構的值如下:
Available = Available - Requests_i; Allocation[i] = Allocation[i] + Requests_i; Need[i] = Need[i] - Requests_i;
- 系統執行安全性算法,如果顯示安全,則正式將資源分配給該進程,否則之前的試探分配作廢,數據解放恢復到原有的值。
- 安全性算法
從上面的銀行家算法的描述可知,安全性算法是整個銀行家算法的關鍵所在。
工作向量work表示在算法執行過程中,系統可以提供給進程繼續運行所需的各類資源數目,含有m個元素,安全算法開始時,work = Available。
完成向量finish表示系統能否運行完成,若finish[i] = true,表示第i個進程可以運行完成。初始時,finish的各個值均為false,當有足夠的資源分配給進程i時,finish[i] = true。
安全算法的步驟如下:
- 設置兩個工作向量。設置工作向量work,完成向量finish,並賦初值。
- 進行安全性檢查。在進程集合中尋找這樣的一個進程:
\(finish[i] = false; Need[i] \leq work;\)
若找得到則執行步驟c,否則執行步驟d。
- work = work + Allocation[i]; //這裡之所以是用“+”是因為當該進程滿足安全性時,系統直接默認該進程已經執行完成,釋放該進程的所有資源,再模擬接下來要進行的情況。同樣,在真正的分配資源,進程也要按照這個順序來執行以避免死鎖。
finish[i] = true;
返回步驟b。
- 若所有進程的finish[i] = true都滿足,則表示系統處於安全狀態,正式分配資源。否則不會進行資源分配。
例:某系統有同類資源m個,有n個並發進程可共享該資源。則每個進程最多可申請多少個該類臨界資源才能保證不發送死鎖?
? 答:要保證不發生死鎖,則要求在最壞的情況下也不能發生死鎖,即n個進程同時請求最大數量的臨街資源時至少有一個進程能夠得到滿足,這樣才不會發生死鎖。
設最大請求資源數量為x。則在最壞的情況下有:
\[ n(x - 1) + 1 \leq m \]
10.死鎖的檢測與解除
10.1 死鎖檢測的時機
- 在發生資源請求時進行檢測,但是在沒有死鎖時會造成非常大的CPU開銷。
- 每隔一段時間,週期性的進程檢測。檢測CPU的使用率,當死鎖出現時,各進程均進入阻塞狀態,無法進入CPU執行,所以CPU的使用率下降。檢測CPU的使用率可以有效檢測到死鎖。
10.2 死鎖的檢測
- 資源分配圖
系統對資源的分配可以用有向圖來表示,該圖由結對組成G = (V,E)。其中V是頂點的集合,E是有向邊的集合。頂點集合可分為進程集合P={p1,p2,p3...}和資源集合R = {r1,r2,r3....}。
在邊集合E中,由有序結對(\(p_i,r_j\))和\((r_j,p_i)\)組成。
\((p_i,r_j)\)叫申請邊,是進程\(p_i\)指向\(r_j\)的有向邊,表示進程\(p_i\)申請一個\(r_j\)資源單位,當前\(p_i\)正在等待。
\((r_j,p_i)\)叫賦給邊,表示有一個資源\(r_j\)已經賦給了進程\(p_i\)。
- 死鎖定理
通過資源分配圖易知,當圖中出現環路時,就表示出現了死鎖。不存在則沒有死鎖。
- 死鎖檢測的算法
- 置初值,work = Available
將不需要也不佔用資源的進程放入表L中。
- 從進程集合中尋找這樣的進程:
\(requests_i \leq work\),且該進程不在表L中。
若能找到,則將其放入L中,增加工作量:
work = work + Allocation[i];
返回步驟b。
- 若不能將所有的進程都放入L中,則發生了死鎖。需要執行死鎖的恢復策略。
- 置初值,work = Available
10.3 死鎖的解除
一般採用兩種方式來解除死鎖:終止一個或多個進程的執行來破壞循環;搶佔參與死鎖的進程的資源。
如果經常從一個進程搶佔資源,則該進程就會經常因為資源不足而無法運行。因此一般情況下總是從執行時間短的進程搶佔資源。
在學習完死鎖後,會發現死鎖中的搶佔資源和安全的執行序列等會影響到前面講過的調度算法。在實際進程的執行過程中,需要同時考慮到這些方面。因此如果想要寫一個實際的操作系統內核的話,這一方面的內容還要繼續深入學習。
原文地址:https://www.cnblogs.com/lunar-ubuntu/p/12242969.html