1. 程式人生 > >作業系統-程序(7)死鎖和銀行家演算法

作業系統-程序(7)死鎖和銀行家演算法

允許多個程序併發執行共享系統資源時,系統必須提供同步機制和程序通訊機制。然而,對這種機制使用不當的話,可能會出現程序永遠被阻塞的現象。例如,兩個程序分別等待對方佔有的一個資源,於是兩者都不能執行而處於永遠等待,這種現象稱為死鎖。 死鎖產生的四個必要條件:
  1. 互斥條件: 程序應互斥使用資源,任一時刻一個資源僅為一個程序獨佔 
  2. 佔有和等待條件: 一個程序請求資源得不到滿足而等待時,不釋放已佔有的資源
  3. 不剝奪條件: 任一程序不能從另一程序那裡搶奪資源
  4. 迴圈等待條件: 存在一個迴圈等待鏈,每一個程序分別等待它前一個程序所持有的資源
破壞第一個條件,把獨佔型資源改造成共享性資源,使資源可同時訪問而不是互斥使用。這是一個簡單的辦法,但對許多資源往往是不能做到的 採用靜態分配可以破壞第二個條件。所謂靜態分配是指一個程序必須在執行前就申請它所要的全部資源,並且直到它所要的資源都得到滿足之後才開始執行,所有併發執行的程序要求的資源總和不超過系統擁有的資源數。採用靜態分配後,程序在執行中不再申請資源,因而不會出現佔有了某些資源再等待另一些資源的情況。但這麼做資源使用率不高。 採用剝奪式排程方法可以破壞第三個條件,但剝奪式排程方法目前只適用於對主存資源和處理器資源的分配,而不適用於所有資源。 層次分配策略將阻止第四個條件的出現,資源被分成多個層次,一個程序得到某一層的一個資源後,它只能再申請更高層的資源;當一個程序要釋放某層的一個資源時,必須先釋放所佔用的更高層的資源; 當一個程序獲得了某一層的一個資源後,它想再申請該層中的另一個資源,那麼,必須先釋放該層中的已佔資源。 當不能防止死鎖的產生時,如果能掌握併發程序中與每個程序有關的資源申請情況,仍然可以避免死鎖的發生。只需在為申請者分配資源前先測試系統狀態,若把資源分配給申請者會產生死鎖的話,則拒絕分配,否則接收申請,為它分配資源。 銀行家演算法(資源分配拒絕法):每個程序pk必須預先說明所要的最大資源量Clain[k , *],每次提出部分資源的申請Request[k , *]並獲得分配;如果作業系統所擁有的最大資源量滿足程序對資源的最大需求量Need[k , *],那麼作業系統一定會接納程序並滿足其資源需求,程序在執行後應在有限時間內將資源全部歸還作業系統;作業系統在收到一個程序的資源申請時,可能會因資源不足而讓程序等待,但保證在有限時間內讓程序獲得資源。 演算法考慮的最壞的情況:所有程序同時要使用它們所宣告的資源最大需求數。此時作業系統中所有程序加上新啟動程序對資源Ri的需求量,不能超過系統擁有的最大資源數。 即系統若要啟動一個新程序工作,其對資源Ri的需求必須滿足Ri ≥ Clain[1 , i] + …+ Clain[n , i] + Clain[n+1 , i] 系統安全性:存在一個程序序列,對程序pk滿足Need[k , i] ≤ Available[i] + Allocation[1 , i] + … + Allocation[n , i] 銀行家演算法分配步驟: (1)若Request[i , *] ≤ Need[i , *],則程序的資源申請量超過了自身的最大需求量,出錯處理 (2)若Request[i , *] ≤ Available[i , *],則程序的資源申請量超過了作業系統當前擁有的最大資源量,讓其等待 (3)系統對程序pi請求的資源進行試探性分配             Allocation[i , *] = Allocation[i , *] + Request[i , *]             Available[*] = Available[*] - Request[i , *]             Need[i , *] = Need[i , *] - Request[i , *] (4)轉向安全測試演算法,如果返回安全狀態則承認試分配,否則拋棄試分配,程序等待,還原試分配的操作 (5)執行初始化操作,定義工作向量集合Work[i] = Available[*]。從程序集合中找到滿足need[k , *] ≤ Work[*]的程序pk,找到後釋放其佔有的資源,Work[*] = Work[*] + Allocation[k , *],把pk從程序集合中去掉,再繼續找下一個程序,直到找到安全的、絕對不會產生死鎖的程序執行序列。 解決死鎖問題的另一條途徑是死鎖檢測方法,這種方法對資源的分配不加限制,但系統定時執行一個死鎖檢測程式,判斷系統內是否已出現死鎖,若檢測到死鎖則設法加以解除。 檢測的一種方法:可設定兩張表格來記錄程序使用資源的情況 等待資源表記錄每個被阻塞程序等待的資源,佔用資源表記錄每個程序佔有的資源 程序申請資源時,先查該資源是否為其它程序所佔用;若資源空閒,則把該資源分配給申請者且登入佔用資源表;否則,則登入等待資源表
死鎖檢測程式定時檢測這兩張表,若有程序Pi等待資源R,且資源R被程序Pj佔用,則說Pi和Pj具有“等待佔用關係”,記為W(Pi, Pj) 死鎖檢測程式反覆檢測這兩張表,可以列出所有的“等待佔用關係” 如果出現W(Pi, Pj)、W(Pj, Pt)、……、W(Pm, Pn)、W(Pn, Pi)時,系統中存在一組迴圈等待資源的程序,也就是說出現了死鎖 把兩張表格中記錄的程序使用和等待資源的情況用一個矩陣A來表示 死鎖檢測程式可用Warshall的傳遞閉包演算法檢測是否有死鎖發生,該演算法通過動態規劃將問題分段,R(k)矩陣只允許路徑中包含前k個頂點作為中間頂點,通過一系列n階矩陣R(k)來構造最終階段n階傳遞閉包矩陣R(n),即R(k)由它的前趨R(k-1)計算得到。
for
k:=1 to n do for i:=1 to n do for j:=1 to n do bij:= bij ∨ (bik ∧ bkj)
也可以用類似銀行間演算法的方法檢測死鎖的存在。最後留在程序集合中的程序就是處於死鎖中的程序。 檢測出死鎖後,解除系統死鎖的方法主要有: (1)結束所有程序的執行並重新啟動作業系統 (2)撤銷陷入死鎖的所有程序,解除死鎖,繼續執行 (3)逐個撤銷陷入死鎖的程序,回收其資源並重新分派,直至死鎖解除。先撤銷的程序可以選擇CPU消耗時間最少者、產生的輸出量最少者、預計剩餘執行時間最長者、分得的資源數量最少者、優先順序最低者 (4)剝奪陷入死鎖的程序所佔用的資源,但不撤銷程序,直到死鎖解除 (5)根據系統儲存的檢查點讓所有程序回退,直到足以解除死鎖(要求系統建立儲存檢查點、回退、重啟機制)