操作系統複習攻略:進程死鎖

資源

資源:軟件、硬件、信息,我們把這類需要排他性使用的對象稱爲資源。當某個資源有多個實例時,其中任何一個都可以用來滿足對資源的請求。簡單來說,資源就是隨着時間的推移,必須能獲得、使用以及釋放的任何東西。

資源分爲兩類:可搶佔的和不可搶佔的。

可搶佔資源可以從擁有它的進程中搶佔而不會產生任何副作用,存儲器就是一類可搶佔的資源。

不可搶佔資源是指在不引起相關的計算失敗的情況下,無法把它從佔有它的進程處搶佔過來。

使用一個資源所需要的時間順序可以用抽象的形式表示如下:

  1. 請求資源
  2. 使用資源
  3. 釋放資源
  • 資源獲取*
typedef int semaphore;
semaphore resource_1; 
semaphore resource_2; 

void process_A(void){
    down(&resource_1);
    use_resource_1();
    up(&resource_1);
}

死鎖簡介

死鎖定義

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

資源死鎖:競爭資源的進程集合按一定順序運行形成死鎖。

死鎖條件

資源死鎖的四個必要條件

  1. 互斥條件。每個資源要麼已經分配給了一個進程,要麼就是可用的。
  2. 佔有和等待條件。已經的到了某個資源的進程可以再請求新的資源。
  3. 不可搶佔條件。已經分配給一個進程的資源不能強制性地被搶佔,它只能被佔有它的進程顯式地釋放。
  4. 環路等待條件。死鎖發生時,系統中一定有由兩個或兩個以上的進程組成一條環路,該環路中的每個進程都在等待着下一個進程所佔有的資源。

死鎖建模

  • Deadlock

在這裏插入圖片描述

  • No Deadlock

在這裏插入圖片描述

有四種處理死鎖的策略:

  1. 忽略該問題。
  2. 檢測死鎖並恢復。讓死鎖發生,檢測它們是否發生,一旦發生死鎖,採取行動解決問題。
  3. 仔細對資源進行分配,動態地避免死鎖。
  4. 通過破壞死鎖的四個必要條件之一,防止死鎖的產生。

死鎖檢測和恢復

死鎖檢測

每種類型一個資源的死鎖檢測

對於每種資源類型只有一個資源,可以對這樣的系統構造一張資源分配圖,如果這張圖包含了一個或一個以上的環,那麼死鎖就存在,在此環中的任何一個進程都是死鎖進程。

  • 如下的資源分配圖:○表示進程,□表示資源,□→○表示進程佔用資源,○→□表示進程請求資源

在這裏插入圖片描述

死鎖檢測算法是依次將每個節點作爲一棵樹的根節點,並進行深度優先搜索,如果碰到了已經遇到過的節點,那麼就算找到了一個環。

每種類型多個資源的死鎖檢測

  • 如下的資源矩陣:E 是現有資源向量,A 是可用資源向量,C 代表當前分配矩陣(第 n 行是進程 n 當前已分配到的資源),R 代表請求矩陣(第 n 行是進程 n 需要的資源)

在這裏插入圖片描述

死鎖檢測算法如下:

  1. 尋找一個沒有標記的進程 Pi,對它而言 R 矩陣的第 i 行向量小於等於 A。
  2. 如果找到了這樣一個進程,那麼將 C 矩陣的第 i 向量加到 A 中,標記該進程,並轉到第1步,表示該進程可以得到所需資源並運行完成。
  3. 如果沒有這樣的進程,那麼算法終止。
  4. 算法結束時,所有沒有標記過的進程都是死鎖進程。

死鎖恢復

  • 利用搶佔恢復
  • 利用回滾恢復
  • 通過殺死進程恢復

死鎖避免

資源軌跡圖

  • 資源軌跡圖:進程 A 在 I1 到 I3 使用打印機,I2 到 I4 使用繪圖儀;進程 B 在 I6 到 I8 使用打印機,I5 到 I7 使用繪圖儀

在這裏插入圖片描述

圖中的陰影部分表示兩個進程同時使用打印機或繪圖儀,而這是不可能實現的,所以不可能進入該區域。

如果系統一旦進入由 I1、I2、I5 和 I6 組成的矩形區域,那麼最後一定會到達 I2 和 I6的交叉點,此時產生死鎖。

安全狀態和不安全狀態

  • 安全狀態:狀態 a 爲安全狀態

在這裏插入圖片描述

  • 不安全狀態:狀態 b 爲不安全狀態

在這裏插入圖片描述

  • 安全狀態,不安全狀態和死鎖

在這裏插入圖片描述

不安全狀態並不是死鎖,在不安全狀態系統還能運行一段時間,甚至還有一些進程可以運行完成。

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

單個資源的銀行家算法

Dijkstra 提出了一種能夠避免死鎖的調度算法,稱爲銀行家算法,這是上面通過檢測死鎖算法的擴展。

  • 單個資源的銀行家算法:Has 表示已有數量,Max 表示最大需求,下圖中 a,b安全,c 不安全

在這裏插入圖片描述

銀行家算法就是對每一個請求進行檢查,檢查如果滿足這一請求是否會達到安全狀態。若是,那麼就滿足該需求;否則,就推遲對這一請求的滿足。

爲了檢查狀態是否安全,銀行家需要考慮他是否有足夠的資源滿足某一客戶。如果可以,那麼這筆貸款是能夠收回的,並且接着檢查最接近最大限額的一個客戶,以此類推。如果所有投資最終都能被收回,那麼該狀態是安全的,最初的請求可以批准。

多個資源的銀行家算法

  • 多個資源的銀行家算法:左矩陣表示已分配資源,右矩陣表示仍然需要的資源,E 表示現有資源,P 表示已分配資源,A 表示可用資源

在這裏插入圖片描述

同上面資源矩陣的檢測算法。


死鎖預防

破壞互斥條件

如果一個資源不被一個進程獨佔,那麼死鎖肯定不會產生。

通過採用假脫機(打印機)技術可以允許若干個進程同時產生輸出。該模型中唯一真正請求物理打印機的進程是打印機守護進程,由於守護進程不會請求別的資源,所以不會因打印機而產生死鎖。

可以考慮爲所有資源建立一個資源池

破壞佔有並等待條件

禁止已持有資源的進程再等待其他資源。

  • 實現方法一:規定所有進程在開始執行前請求所需的全部資源。
  • 實現方法二:當一個進程請求資源時,先暫時釋放其當前佔用的所有資源,然後再嘗試一次獲得所需的全部資源。

破壞不可搶佔條件

搶佔正在打印的打印機可能會造成混亂,但是可以對這類資源可以採用虛擬化的方式來避免發生這類情況,假脫機打印機向磁盤輸出。

破壞環路等待條件

  • 實現方法一:保證每個進程在任何時刻只能佔用一個資源,如果要請求另外一個資源,它必須先釋放第一個資源。
  • 實現方法二:將所有資源統一編號,進程可以在任何時刻提出資源請求,但是所有請求必須按照資源編號順序(升序)提出。

其他問題

兩階段加鎖

在第一階段,進程試圖對所有所需的記錄進行加鎖,一次鎖一個記錄。如果第一階段加鎖成功,就開始第二階段,完成更新然後釋放鎖。在第一階段並沒有做實際的工作。如果在第一階段某個進程需要的記錄已經被加鎖,那麼該進程釋放它所有加鎖的記錄,然後重新開始第一階段。

通信死鎖

資源死鎖是最普遍的一種類型,但不是唯一的一種。

通信死鎖發生在通信系統(e.g. 網絡)中,一個普遍的情形是:進程 A 向進程 B 發送請求信息,然後阻塞直至 B 回覆,但是請求信息在網絡中丟失,A 將阻塞以等待回覆,而 B 也會阻塞等待一個向其發送命令的請求,因此發送死鎖。

可以設置適當的超時機制來解決通信死鎖。

活鎖

在某些情況下,當進程意識到它不能獲取所需要的下一個鎖時,就會釋放已經得到的鎖,等待1ms,然後再嘗試一次,但是,如果另一個進程在相同的時刻做了相同的操作,那麼兩個進程就像兩個人在一條路相遇並同時給對方讓路一樣,相同的步調將導致雙方都無法前進。

保持飢餓:SJF

一些管理資源的策略可能使一些進程永遠得不到服務,比如最小作業優先策略,可以使用先進先出的分配策略來避免飢餓。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章