1. 程式人生 > >現代作業系統: 第六章 死鎖

現代作業系統: 第六章 死鎖

在計算機系統中有很多獨佔性的資源,在任意時刻中都只能被一個程序所佔有。

6.1 資源

在程序對裝置、檔案等取得了排他性訪問權的時候,有可能會產生死鎖。為了儘可能使關於死鎖的討論通用,我們把這類需要排他性使用的物件稱為資源

6.1.1 可搶佔性資源和不可搶佔性資源

  • 可搶佔性資源:可以從擁有它的程序中搶佔而不產生任何副作用,儲存器就是一種可搶佔性的資源。
  • 不可搶佔性資源:不引起相關的計算失敗的情況下,無法從佔有它的程序中搶佔過來,這種資源就稱為不可搶佔性資源。

使用一個資源所需要的事件順序可以用抽象的形式表現出來:

  1. 請求資源。
  2. 使用資源。
  3. 釋放資源。

6.1.2 資源獲取

一種允許使用者管理資源的方法就是為每一個資源配置一個訊號量。這個訊號量初始化為1。互斥訊號量也能起到相同的作用。上述的三個步驟可以實現為訊號量的down操作來獲取資源、使用資源、最後使用up操作來釋放資源。

6.2 死鎖定義

如果一個程序集合中的每個程序都在等待只能由該程序集合中的其他程序才能引發的事件,那麼該程序集合就是死鎖的。

細節解釋:在大多數情況下,每個程序所等待的時間是釋放程序集合中其他程序所佔有的資源。換言之,這一個死鎖程序集合中的每一個程序都在等待另一個死鎖程序已經佔有的資源。但是由於所有程序都不能執行,他們中的任何一個程序都無法釋放資源,所以沒有一個程序可以被喚醒。這種死鎖稱為資源死鎖。

6.2.1 死鎖發生的條件

1) 互斥條件:每個資源要麼已經分配給了一個程序,要麼就是可用的

2) 佔有和等待條件:已經得到了某個資源的程序可以再請求新的資源,如果該資源被其他程序佔有,則當前程序進入等待狀態

3) 不可搶佔條件:已經分配的資源不能被搶佔,只能由佔有它的程序顯式釋放

4) 環路等待條件:系統中有兩個或兩個以上程序形成環路,環路中每個程序都在等待下一個程序所佔有的資源

6.2.2 死鎖建模

Holt指出如何用有向圖建立上述四個條件的模型。在有向圖中有兩類節點:用圓形表示的程序,用方形表示的資源。從資源節點到程序節點的有向邊代表該資源已被請求,授權並被程序所佔用。從程序節點到資源節點的有向邊表示當前程序正在請求資源,並且該程序已經被阻塞,處於等待該資源的狀態。

在這裡插入圖片描述

總而言之,有四種處理死鎖的策略:

1) 忽略該問題(鴕鳥演算法)

2) 檢測死鎖並恢復

3) 仔細對資源進行分配,動態地避免死鎖

4) 通過破壞引起死鎖的四個必要條件之一,防止死鎖發生

6.3 鴕鳥演算法

忽略該問題(鴕鳥演算法)

6.4 死鎖檢查並恢復

系統並不試圖到死鎖產生,而是允許死鎖傳送,當檢測到死鎖後,採取措施進行恢復。

  1. 每種型別一個資源的死鎖檢測

建模檢測是否有環

  1. 每種型別多個資源的死鎖檢測

當前分配矩陣C,請求矩陣R

步驟:

(1)尋找一個沒有標記的程序Pi,對它而言R矩陣的第i行向量小於等於A。

(2)如果找到了這樣一個程序,那麼將C矩陣的第i行向量加到A中,標記該程序,並轉到第一步。

(3)如果沒找到,演算法終止。

如果演算法結束,存在沒有標記的程序,則為死鎖程序。

6.4.3 從死鎖中恢復

1.利用搶佔恢復(要求資源本身允許搶佔)

在某些情況下,可能會臨時將某個資源從它的當前所有者那裡轉移給另一個程序。許多情況下,尤其對於執行在大型主機上的批處理作業系統來說,需要進行人工干預。

2.利用回滾恢復(將狀態寫入檔案以備重啟)

一旦檢測到死鎖,就很容易發現需要哪些資源。為了進行恢復,要從一個較早的檢查點開始,這樣所擁有的所需要資源的程序會回滾到一個時間點。實際上,是將該程序回滾一個更早的狀態,那時它還沒有取得所需要的資源,接著就把這個資源分配給另一個死鎖程序。如果復位後的程序試圖重新獲取對該資源的控制,它就必須等待該資源可用為止。

3.通過殺死程序恢復(資料庫可能不允許這樣)

最直接也是最簡單的解決死鎖的方法是殺死一個或者若干個程序。一種方法是殺掉環中的一個程序。如果走運的話,其他程序將也可以繼續。如果這樣行不通的話,就需要繼續殺死別的程序知道打破死鎖破壞。

6.5 死鎖避免

安全狀態和不安全狀態的區別:從安全狀態出發,系統能夠保證所有程序都能完成, 而不安全狀態則沒有這樣的保證

不安全狀態不是死鎖,死鎖意味著程序程序都鎖死不能執行,而不安全狀態則可以執行一段時間。

不安全狀態不一定會引起死鎖,但是不安全狀態可能會導致死鎖。

在這裡插入圖片描述

銀行家演算法

6.6 死鎖預防

6.6.1 破壞互斥條件

如果資源不被一個程序所獨佔,那麼死鎖肯定不會發生。當然,允許兩個程序同時使用印表機會造成混亂,通過採用假離線技術可以執行若干個程序同時佔有資源。

6.6.2 破壞佔有並等待資源

只要禁止已經持有資源的程序再等待其他資源就可以消除死鎖。一種實現方法就是規定所有程序再開始執行前請求所需要的全部資源。如果所需要的全部資源可用,那麼久將他分配給這個程序,於是該程序肯定能執行結束。如果有一個或者多個資源正在被使用,那麼就不進行分配,程序等待。

6.6.3 破壞不可搶佔條件

通過虛擬化方式進行搶佔,並只允許假離線印表機向磁碟輸出,並只允許守護程序訪問真正的物理印表機。

6.6.4 破壞環路等待條件

消除環路等待條件有幾種方法:

  • 保證每一程序都只能在任何時刻都只能還在納雍一個程序,如果要請求其他另外一個資源,它必須釋放第一個資源。

  • 將所有資源進行編號。現在的規則是:程序可以在任何時刻提出資源請求,但是所有請求必須按照資源編號的順序(升序)提出。

在這裡插入圖片描述

6.7 其他問題

6.7.1 兩階段鎖

在資料庫系統中,一個經常發生的操作就是請求鎖住一些記錄,然後更新所有鎖住的記錄。

第一階段:試圖對所有所需記錄加鎖,如某個程序已被加鎖,釋放該程序的所有加鎖記錄,重新開始第一階段。

第二階段:第一階段加鎖成功後,完成更新然後釋放鎖。

該演算法只適用於程式設計師可以安排程式停下和重新開始而不會產生錯誤的情況(如資料庫系統)。

6.7.2 通訊死鎖

在一系列程序中,每個程序因為等待另外一個程序引發的事件而產生阻塞,可採用超時機制解決。

在大多數網路通訊系統中,只要有一個訊息被髮送到一個特定的地方,並等待其返回一個預期的回覆,傳送者就同時啟動計時器。若計時器在回覆到達前計時就停止了,則訊息的傳送者可以認定訊息已經丟失,並重新發送。

6.7.3 活鎖

沒有阻塞但也沒有進展。通過輪詢代替阻塞,只是沒有阻塞而已。

6.7.4 飢餓

程序無限制地推後,得不到執行,可採用先來先服務資源分配策略避免。