操作系統概念學習筆記 14 死鎖(二)

操作系統概念學習筆記 14

死鎖(二)


死鎖避免(deadlock-avoidance)

在上篇博客中討論的死鎖預防問題中,通過限制資源申請的方法預防死鎖。這種限制保證4個必要條件之一不會發生,保證不會發生死鎖,然而通過這種方式預防死鎖的副作用是低設備使用率和系統吞吐率。

避免死鎖的另外一種方法是獲得以後如何申請資源的附加信息。

不同的算法所要求的信息量和信息的類型上有所不同,最爲簡單和最爲常用的模型要求每個進程說明可能需要的每種資源類型實例的最大需求。根據每個進程可能申請的每種資源類型實例的最大需求的事先信息,可以構造一個算法以確保系統絕不會進入死鎖狀態。這種算法定義了死鎖避免(deadlock-avoidance)方法。

死鎖避免算法動態的檢測資源分配狀態以確保循環等待條件不可能成立。資源分配狀態是由可用資源和已分配資源,以及進程最大需求所決定的。

安全狀態:

如果系統能按某個順序爲每個進程分配資源(不超過其最大值)並能避免死鎖,那麼系統狀態就是安全的。即如果存在一個安全序列,那麼系統處於安全狀態。如果沒有這樣的順序存在,那麼系統處於不安全狀態。

進程順序{P1, P2, …, Pn},如果對於每個Pi,Pi仍然可以申請的資源數小於當前可用資源加上所有進程Pj(其中j小於i)所佔用資源,那麼這一順序稱爲安全序列。

在這種情況下,進程Pi所需要的資源即使不能立即使用,那麼Pi等待直到所有Pj釋放其資源,當它們完成時,Pi可得到其所需要的所有資源,完成其給定任務。

安全狀態不是死鎖狀態,相反,死鎖狀態是不安全狀態。然而,不是所有不安全狀態都能夠導致死鎖狀態。

只要狀態爲安全,操作系統就能避免不安全(和死鎖)狀態。在不安全情況下,操作系統不能阻止進程以會導致死鎖的方式申請資源。進程行爲控制了不安全狀態。

這裏寫圖片描述

例如考慮一個系統,有12臺磁帶驅動器和三個進程P0,P1,P2,目前狀況如下表:

進程 最大需求 當前需求
P0 10 5
P1 4 2
P2 9 2

順序{P1,P0,P2}滿足安全條件,因爲:

  • 對於P0,5小於等於2+3
  • 對於P1,2小於3
  • 對於P2,7小於2+5+3

系統可以從安全狀態轉變爲不安全狀態,加入某時刻,進程P2申請並又得到了一臺磁帶驅動器,系統就不再安全了。

進程 最大需求 當前需求
P0 10 5
P1 4 2
P2 9 3

此時P0還需要5臺,但是系統只剩4臺了,必須等待,同時P2還需要6臺,也必須等待,由此導致了死鎖。

造成這個錯誤的原因即允許P2再獲取了一臺磁帶驅動器。

有了安全狀態的概念,可定義避免算法確保系統不會死鎖,即確保系統處於安全狀態,開始,系統處於安全狀態,當進程申請一個可用資源時,系統必須確定這一資源申請是可以立即分配還是要等待,即便現在資源可用,也只有分配後系統仍處於安全狀態,才允許申請。

也因此採用這種方法和沒有采用死鎖避免算法相比資源使用率可能更低。

資源分配圖算法:

利用資源分配圖,引入需求邊Pi->Rj表示進程Pi可能在將來某個時候申請資源Rj。只有申請邊變爲分配邊而不會導致資源分配圖形成環時,才允許申請。

如果沒有環存在,那麼會使得系統處於安全狀態,如果有環存在則分配會導致系統處於不安全狀態。

例如:

這裏寫圖片描述

假如進程p2申請資源R2。雖然R2現在可用,但是不能分配給P2,因爲這會創建一個環,環表示系統處於不安全狀態,如果P1再申請R2就會造成死鎖。

銀行家算法:

銀行家算法:對於每種資源類型有多個實例的資源分配系統,資源分配圖就不再適用。使用銀行家算法,但是效率比資源分配圖方案低。

當新進程進入系統時,它必須說明其可能需要的各種類型資源實例的最大數量,這一數量不能超過當前系統資源的總和。當用戶申請一組資源時,系統必須確定這些資源的分配是否仍會使系統出於安全狀態,如果是,就分配資源;否則,進程必須等待直到某個其他進程釋放足夠資源爲止。

實現銀行家算法,必須有幾個數據結構:AvailableMaxAllocationNeed

這些數據結構對資源分配系統的狀態進行了記錄。設n爲系統的進程的個數,m爲資源類型的種類:

  • Available:長度爲m的向量,表示每種資源類型的現有實例的數量。如果Available[j] = k,則說明資源類型Rj有現有k個實例。

  • Max:nXm矩陣,定義每個進程的最大需求,如果Max[i][j] = k,那麼進程Pi最多申請k個資源類型Rj的實例。

  • Allocation:nXm矩陣,定義每個進程現在所分配的各種資源類型的實例數量,例如Allocation[i][j] = k,那麼進程Pi現在已經分配了k個資源類型Rj的實例。

  • Need:nXm矩陣,表示每個進程還需要的剩餘的資源。如果Need[i][j] = k,那麼進程Pi還需要申請k個資源類型Rj的實例。並且Need[i][j] =  Max[i][j]  - Allocation[i][j]

這些數據結構的大小和值會隨着時間而改變。

爲了簡化銀行家算法的描述:

設X,Y爲長度爲n的向量,那麼X <= Y 當且僅當對所有的i = 1,2,3…,n ,X[i] <= Y[i],如果X <= Y 並且X!=Y,那麼Y小於X。

可以將矩陣Allocation 和Need的每行作爲向量,並分別用Allocationi 和Needi來表示。

向量Allocationi表示分配給進程Pi的資源,Needi表示進程Pi爲完成其任務可能仍然需要申請的額外資源。

安全性算法

確定計算機是否處於安全狀態需要以下幾步:

  • 1 創建Work 和 Finish 向量,長度分別爲m,n,並且Work = Avallable,將Finish的每一項置爲false

  • 2 查找是否存在這樣的i使得滿足:

    Finish[i] = false

    Needi <= Work

如果不存在則跳到第四步。

  • 3

    Work = Work + Allocationi

    Finish[i] = true

跳回第二步

  • 4 如果對所有的i,Finish[i] = true,那麼系統處於安全狀態。

資源請求算法

設Requesti爲進程Pi的請求向量。即如果Requesti[j] == k ,那麼Pi所需要資源類型Rj的實例數量爲k。

當進程Pi做出資源申請時,採取如下動作:

  • 1 如果Requesti < Needi,那麼進行下一步,否則產生出錯條件,因爲已經超過了其最大請求。

  • 2 如果Requesti < Available,那麼進行下一步,否則Pi必須等待,因爲沒有可用的資源。

  • 3 假定系統可以分配給進程Pi所需的資源,並按如下方式修改狀態:

Available = Available - Requesti

Allocationi = Allocationi + Requesti

Needi = Needi - Requesti

如果所產生的資源分配狀態是安全的,那麼交易完成且進程Pi可分配到其所需要的資源。

然而,如果新狀態不安全,那麼進程Pi必須等待Requesti並回復到原資源分配狀態。

舉例

假定系統中有4個進程P1、P2、P3、P4和3種類型的資源R1、R2、R3,數量分別爲9、3、6,在t0時刻的資源分配情況如表所示。

t0時刻的資源分配表:

這裏寫圖片描述

試問:

(1)t0時刻是否安全?

(2)P2發出請求向量Request2(1,0,1),系統能否將資源分配給它?

(3)在P2申請資源後,若P1發出請求向量Request1(1,0,1),系統能否將資源分配給它?

(4)在P1申請資源後,若P3發出請求向量Request3(0,0,1),系統能否將資源分配給它?

解答:

(1)安全序列:P2、P1、P3、P4

(2)可以分配,因爲分配資源後可找到一安全序列:P2、P1、P3、P4

(3)不能分配,因爲request1(1,0,1)>available(0,1,1)

(4)不能分配,因爲分配資源後找不到一安全序列。

死鎖檢測

檢測和恢復都會有額外的開銷:這不僅包括維護所需信息和執行檢測算法的運行開銷,而且也包括死鎖恢復所引起的損失。

情況一:每種資源類型只有單個實例:

該算法使用了資源分配圖的變種,等待(wait-for)圖。從資源分配圖中,刪除所有資源類型節點,合併適當邊,就可以得到等待圖。等待圖中由Pi到Pj的邊意味着進程Pi等待進程Pj釋放一個Pi所需的資源。

當且僅當等待圖中有環,系統中存在死鎖。爲了檢測死鎖,系統需要維護等待圖,並週期性調用在圖中進行搜索的算法。從圖中檢測環的算法需要n2級別操作,其中n爲圖中的節點數。

情況二:每種資源類型可有多個實例:

採用與銀行家算法相類似的算法。

  • Available:長度爲m的向量,表示各種資源的可用實例。

  • Allocation:nXm矩陣,表示當前各進程的資源分配情況。

  • Request:nXm矩陣,表示當前各進程的資源請求情況。如果Request[i][j] = k,那麼Pi現在正在請求k個資源Rj。

  • 1 創建Work 和 Finish 向量,長度分別爲m,n,並且Work = Avallable,將Finish的每一項置爲false

  • 2 查找是否存在這樣的i使得滿足:

    Finish[i] = false

    Requesti <= Work

如果不存在則跳到第四步。

  • 3

    Work = Work + Allocationi

    Finish[i] = true

跳回第二步

  • 4 如果對所有的i,Finish[i] == false,那麼系統處於死鎖狀態。而且進程Pi死鎖

應用檢測算法

極端情況下,在每次請求分配不能立即允許時,就調用死鎖檢測算法。但會引起相當大的計算開銷。或以一個不太高的頻率調用檢測算法,但這通常不能確定死鎖進程中哪些“造成”了死鎖。

死鎖恢復

一種措施是通知操作員死鎖已發生,以便操作人員人工處理死鎖。

另一種措施是讓系統從死鎖狀態中自動恢復過來。打破死鎖有兩種方法:一個方法是簡單地終止或多個進程以打破循環等待。

另一個方法是從一個或多個死鎖進程那裏搶佔一個或多個資源。

進程終止:

一是,終止所有死鎖進程,這種方式雖然終止了死鎖循環,代價太大。

二是,一次只終止一個進程直到取消死鎖循環爲止,這種方法的開銷會很大,因爲每次終止一個進程,就需要調用死鎖檢測算法以確定進程是否仍處於死鎖。

資源搶佔:

這裏有三個問題需要處理:

①選擇一個犧牲品:搶佔哪些資源和哪個進程?必須確定搶佔順序以使代價最小化。

②回滾:如果從一個進程那裏搶佔一個資源,那麼應對該進程做些什麼安排?必須將這個進程回滾到某個安全狀態,以便以後重啓進程。

最簡單的方法是完全回滾:終止進程並重新執行。更爲有效的方法是將進程回滾到足夠打破死鎖。另一方面,這種方法要求系統維護有關運行進程狀態的更多信息。

③飢餓:如何確保不會發生飢餓?最爲常用的方法是在代價因素中加上回滾次數。

發佈了87 篇原創文章 · 獲贊 204 · 訪問量 76萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章