【操作系统⑩】——进程死锁【银行家算法+详细样例 进程死锁的预防机制、避免机制、检测与解决】
?? 重點篇
文章目錄
- 一、進程死鎖的概念與條件
- 1.1 死鎖定義
- 1.2 死鎖的典型場景
- 1.3 死鎖的必要條件
- 二、進程死鎖的預防機制
- 2.1 機制原理
- 2.2 解決方案
- 三、進程死鎖的避免機制
- 3.1 機制原理
- 3.2 銀行家算法(Dijkstra在1965年提出) ??????
- 3.2.1 安全狀態
- 3.2.2 算法實質與思想
- 3.2.3 算法所需的相關數據結構
- 3.2.4 算法的設計思想
- 3.2.5 算法的細節補充
- 3.2.6 算法的實戰(樣例)
- 四、進程死鎖的檢測與解決
- 4.1 機制原理
- 4.2 死鎖檢測
- 4.3 死鎖解除
- 五、進程死鎖問題的思考
- 5.1 死鎖原因
- 5.2 解決原則
- 六、參考附錄:
Banker’s algorithm 🏦
上一篇文章地址鏈接: 【操作系統⑨】——進程間通信的概述【kill() signal() shmget() shmat() 實例 共享存儲通信 消息通信 管道通信 】.
下一篇文章地址鏈接: 【操作系統?】——存儲管理(上)【分區存儲管理 分頁存儲管理+詳細樣例】.
期末考試總復習——地址鏈接:《操作系統期末總復習——絕地求生版》.
一、進程死鎖的概念與條件
1.1 死鎖定義
??● 背景:多道進程的并發執行可以改善系統的資源利用率,但也可能出現——“進程相互等待對方釋放資源才能繼續運行”的情況。
??● 死鎖:系統中多個進程無限期地等待永遠不會滿足的條件,處于停滯狀態,稱為進程死鎖。
1.2 死鎖的典型場景
??● 申請同類資源:內存資源有 m 個分配單位,然而有 n(n>m) 個進程共享內存資源,進程每次只能申請一個單位滿足總量才能使用,且每個進程使用完才一次性釋放資源。(假如說,在一個神奇餐廳,有 2 根筷子,此時有 3 個人進來吃飯。①號老哥和②號小姐姐都需要用兩根筷子才能吃飯,而③號小老弟只需要一根筷子就能吃飯。然后,他們三去“搶占”資源,如果出現這種情況——“①號和②號分別搶到一根筷子,③號沒搶到”,則導致死鎖)
??● 申請不同類資源:(假設在辦公室里有一把掃把和一個簸箕。然后有兩個不同班級的同學來拿“資源”去打掃各自教室的衛生。假如說每個同學一次只能拿走一個東西到各自教室,到教室后需要同時有掃把和簸箕才能開始打掃)
進程P1(): | 進程P2(): ... | ... 申請用掃把 | 申請用簸箕 申請用簸箕 | 申請用掃把 clean(P1的教室) | clean(P2的教室) 釋放簸箕 | 釋放掃把 釋放掃把 | 釋放簸箕 ... | ...??● 說明:若 “P1” 拿了掃把后。不一會兒,“P2” 又把簸箕拿走了。這時就會導致死鎖。兩位同學就會在辦公室里面傻傻地等著對方釋放“資源”。
1.3 死鎖的必要條件
??① 互斥使用(資源獨占):指進程對所分配到的資源進行排它性使用,即在一段時間內某資源只由一個進程占用。如果此時還有其它進程請求資源,則請求者只能等待,直至占有資源的進程用畢釋放。
??② 不可強占(不可剝奪):指進程已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它進程占有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放。
??③ 請求保持(部分分配,占有申請):進程在申請新資源的同時保持對原有資源的占有。
??④ 循環等待(環路等待條件):指在發生死鎖時,必然存在一個進程——資源的環形鏈,即進程集合 {P0,P1,P2,···,Pn} 中的 P0 正在等待一個 P1 占用的資源;P1 正在等待 P2 占用的資源,……,Pn 正在等待已被 P0 占用的資源。
??● 理解了死鎖的原因,尤其是產生死鎖的四個必要條件,就可以最大可能地避免、預防和解除死鎖。所以,在系統設計、進程調度等方面注意如何能夠不讓這四個必要條件成立,如何確定資源的合理分配算法,避免進程永久占據系統資源。
二、進程死鎖的預防機制
2.1 機制原理
??● 預先確定資源分配,保證不發生死鎖,通過破壞死鎖 4 個必要條件之一來實現,但破壞 “互斥使用” 這一必要條件不現實。所以一般破壞其他 3 個。
2.2 解決方案
??① 破壞“不可剝奪”:
????<1> 允許進程動態申請資源
????<2> 進程在申請新資源不能得到滿足而變為等待狀態之前,必須釋放已占有的資源
????<3> 若需要資源必須重新申請
??② 破壞“請求保持”:
????<1> 不允許進程動態申請資源
????<2> 進程運行前須一次性申請所需的所有資源
????<3> 進程所要資源均可滿足時給予一次性分配
??(有缺陷 舉例子:比如說,5 個大媽在河邊洗衣服,資源區一共有 1 包洗衣粉、 5 個木桶、5 根打衣棒、5 個水坑位、5 個搓衣板。如果說1 位大媽同時需要 “ 1 個水坑位、 1 包洗衣粉、2 個木桶、1 個打衣棒、1 個搓衣板” 才能開始洗衣服,然后一次性申請這么多資源,只有當這位大媽洗完后才能釋放資源。→→→ 這樣就會導致資源利用率下降,因為這里只有 1 包洗衣粉,而大媽使用洗衣粉也就 10多秒,倒一些出來就完事,沒必要一直占用者)
??③ 破壞“循環等待”:
????<1> 采用資源有序分配法
????<2> 對系統中所有資源進行編號
????<3> 進程須嚴格按資源編號的遞增次序申請資源
????<4> 違反上述規則操作系統不予分配
??(這個主要是預防前面說的——“兩個同學拿掃把簸箕打掃教室衛生”的死鎖情況,但這個也可能導致資源利用率的下降)
三、進程死鎖的避免機制
3.1 機制原理
??● 對進程發出的每一個資源申請進行動態檢查,根據檢查結果決定是否分配資源,若試分配后可能發生死鎖,則不予分配,否則分配。
3.2 銀行家算法(Dijkstra在1965年提出) ??????
??● 銀行家算法是著名的死鎖避免算法:這是一個銀行家給多個顧客分發貸款的算法,可以類比到操作系統給進程分配資源。這時只要把銀行家換成操作系統,把顧客換成進程,把資金換成資源,把銀行家決定是否放貸時所用的判斷過程(即判斷顧客是否有信譽和償還能力)換成操作系統決定是否分配資源時所用的判斷過程(即判斷進程是否能及時歸還資源)即可。
????① 銀行家擁有一筆周轉資金
????② 客戶要求分期貸款,如果能夠得到各期貸款,就一定能夠歸還貸款,否則就一定不能歸還貸款
????③ 銀行家應謹慎地貸款,防止出現壞賬
????④ 銀行家采用的具體方法是看是否有足夠的剩余資金滿足某一客戶,如此反復下去
????⑤ 如果所有投資最終都被收回,則請求可以批準
3.2.1 安全狀態
??● 為了描述銀行家算法,下面先介紹一下系統的安全狀態的概念:
????① 若在某一時刻,系統能按某種進程順序,如 {P1,P2,…,Pn}\{P_1,P_2,…,P_n\}{P1?,P2?,…,Pn?} 為每個進程分配其所需的資源,直至最大需求,使每個進程均可順利完成,則稱此時系統的狀態為安全狀態。稱這樣的一個進程序列 {P1,P2,…,Pn}\{P_1,P_2,…,P_n\}{P1?,P2?,…,Pn?} 為安全序列。
????② 安全序列的實質:序列中的每一個進程 Pi(i=1,2,…,n)P_i(i= 1 ,2,… ,n)Pi?(i=1,2,…,n) 到運行完成尚需的資源量 ≤ 系統當前剩余的資源量 + 所有在序列中排在它前面的進程當前所占有的資源量。
????③ 若在某一時刻,系統中不存在一個安全序列,則稱系統處于不安全狀態。
??◆ 需要注意:
????① 系統在某一時刻的安全狀態可能不唯一,但這不影響對系統安全性的判斷。
????② 安全狀態是非死鎖狀態,而不安全狀態并不一定是死鎖狀態。即系統處于安全狀態一定可以避免死鎖,而系統處于不安全狀態則僅僅是可能進入死鎖狀態。
3.2.2 算法實質與思想
??● 銀行家算法的實質:設法保證系統動態分配資源后不進入不安全狀態,以避免可能產生的死鎖。
??● 銀行家算法的程序思想:
????① 系統中的所有進程進入進程集合。
????② 在安全狀態下系統收到進程的資源請求后,先把資源試探性地分配給它。
????③ 系統用剩下的可用資源和進程集合中其他進程還需要的資源數作比較,在進程集合中找到剩余資源能滿足最大需求量的進程,從而,保證這個進程運行完畢后并能歸還全部資源。
????④ 把這個進程從集合中去掉,系統的剩余資源更多了,然后反復執行上述步驟。
????⑤ 最后,檢查進程集合,若為空則表明本次申請可行,系統處于安全狀態,可實施本次分配;否則,有進程執行不完,系統處于不完全狀態,本次資源分配暫不實施,讓申請進程等待。
3.2.3 算法所需的相關數據結構
??● 考慮一個系統有 n 個進程和 m 種不同類型的資源,現定義包含以下向量和矩陣的數據結構:
??① 可利用資源向量 Resource=(R1,R2,...,Rm)Resource = (R_1,R_2,...,R_m)Resource=(R1?,R2?,...,Rm?)。這是一個含有 mmm 個元素的數組,其中的而每一個元素代表一類可利用資源數目,其初始值是系統中所配置的該類全部可用資源的數目。其數值隨該類資源的分配和回收而動態的改變。如果 Resource[i]=KResource[i]=KResource[i]=K,則表示系統中現有 RiR_iRi? 類資源 KKK 個。【注:后面,一開始初始化時用 Resource 來表示資源數,然后進行初始化分配后,剩余資源數用 Available 來表示 】
??② 最大需求矩陣 MaxMaxMax 。這是一個 n?mn*mn?m 的矩陣,它定義了系統中 nnn 個進程中的每一個進程對 mmm 類資源的最大需求。如果 Max[i,j]=KMax[i,j]=KMax[i,j]=K ;則表示進程 iii 需要 RjR_jRj? 類資源的最大數目為 KKK。
??③ 分配矩陣 AllocationAllocationAllocation 。這也是一個 n?mn*mn?m 的矩陣,它定義了系統中每一類資源當前已分配給每一進程的資源數。如果 Allocation[i,j]=KAllocation[i,j]=KAllocation[i,j]=K,則表示進程 iii 當前已分得 RjR_jRj? 類資源的數目為 KKK。
??④ 需求矩陣 NeedNeedNeed。這也是一個 n?mn*mn?m 的矩陣,用以表示每一個進程尚需的各類資源數。如果 Need[i,j]=KNeed[i,j]=KNeed[i,j]=K,則表示進程 iii 還需要 RjR_jRj? 類資源 KKK 個,方能完成任務。
??⑤ 設 Request[i,j]Request[i,j]Request[i,j] 是進程 PiP_iPi? 的申請向量,如果 Request[i,j]=KRequest [i,j]=KRequest[i,j]=K,則表示進程 PiP_iPi? 需要 KKK 個 RjR_jRj? 類型的資源。
??上述三個矩陣間存在下述關系:Need[i,j]=Max[i,j]?Allocation[i,j]Need[i,j]=Max[i,j]-Allocation[i,j]Need[i,j]=Max[i,j]?Allocation[i,j]
3.2.4 算法的設計思想
??● 設計思路如下:
??第一部分:銀行家算法模塊
??① 如果 Request≤NeedRequest≤NeedRequest≤Need,則轉向 ②;否則,出錯
??② 如果 Request≤AvailableRequest≤AvailableRequest≤Available,則轉向 ③;否則等待
??③ 系統試探性分配請求的資源給進程
??④ 系統執行安全性算法
??第二部分:安全性算法模塊
??① 設置兩個參數
????<1> 工作向量Work工作向量Work工作向量Work:值等于ResourceResourceResource
????<2> 標志變量Finish標志變量Finish標志變量Finish:表示系統是否有足夠資源分配給進程 (True:有True:有True:有,False:沒有False:沒有False:沒有) 。初始化為 FalseFalseFalse。
??② 若 Finish[i]=False&&Need<=WorkFinish[i]=False\,\, \&\& \,\, Need<=WorkFinish[i]=False&&Need<=Work,則執行 ③;否則執行 ④ (iii 為資源類別)
??③ 進程 PPP 獲得第 iii 類資源,則順利執行直至完成,并釋放資源: Work=Work+AllocationWork=Work+AllocationWork=Work+Allocation;Finish[i]=trueFinish[i]=trueFinish[i]=true;轉 ② 。
??④ 若所有進程的 Finish[i]=trueFinish[i]=trueFinish[i]=true,則表示系統安全;否則,不安全!
3.2.5 算法的細節補充
??● 當 PiP_iPi? 發出資源請求后,系統按下述步驟進行檢查:(對標第一部分)
??① 如果 Request[i,j]<=Need[i,j]Request [i,j]<=Need[i,j]Request[i,j]<=Need[i,j],便轉向步驟 ②;否則認為出錯,因為它所需要的資源數已經超過它所申請的最大值。
??② 如果 Request[i,j]<=Available[i,j]Request [i,j]<=Available[i,j]Request[i,j]<=Available[i,j],便轉向步驟 ③;否則,表示尚無足夠資源,PiP_iPi? 需等待。
??③ 系統試探著把資源分配給進程 PiP_iPi?,并修改下面數據結構中的數值:
????Available[j]=Available[j]?Request[i,j];Available[j]=Available[j]-Request [i,j];Available[j]=Available[j]?Request[i,j];
????Allocation[i,j]=Allocation[i,j]+Request[i,j];Allocation[i,j]=Allocation[i,j]+Request [i,j];Allocation[i,j]=Allocation[i,j]+Request[i,j];
????Need[i,j]=Need[i,j]?Request[i,j];Need[i,j]=Need[i,j]-Request [i,j];Need[i,j]=Need[i,j]?Request[i,j];
??④ 系統再執行安全性算法,檢查此次資源分配后系統是否處于安全狀態。若安全,才正式將資源分配給進程 PiP_iPi?,以完成本次分配;否則,將本次的試探分配作廢,恢復原來的資源分配狀態,讓進程 PiP_iPi? 等待。
??● 系統所執行的安全性算法可描述如下:(對標第二部分)
??① 設置兩個參數
????<1> 工作向量Work工作向量Work工作向量Work:表示系統可提供給進程繼續運行所需的各類資源數目,它含有 mmm 個元素,在執行安全算法開始時,進行初始化賦值 Work=AvailableWork=AvailableWork=Available。
????<2> 標志變量Finish標志變量Finish標志變量Finish:表示系統是否有足夠的資源分配給進程,使之運行完成。開始時先做 Finish[i]=falseFinish[i]=falseFinish[i]=false;當有足夠資源分配給進程時,再令 Finish[i]=tureFinish[i]=tureFinish[i]=ture。
??② 從進程集合中找到一個滿足下述條件的進程:
????<1> Finish[i]=falseFinish[i]=falseFinish[i]=false;
????<2> Need[i,j]<=Work[j]Need[i,j]<=Work[j]Need[i,j]<=Work[j];若找得到,執行步驟 ③,否則,執行步驟 ④。
??③ 當進程 PiP_iPi? 獲得資源后,可順利執行,直至完成,并釋放出分配給它的資源,故應執行:
????<1> Work[j]=Work[j]+Allocation[i,j]Work[j]=Work[j]+Allocation[i,j]Work[j]=Work[j]+Allocation[i,j];
????<2> Finish[i]=trueFinish[i]=trueFinish[i]=true;
????<3> Gotostep②Go\,\,\, to\,\,\, step ②Gotostep②;
??④ 如果所有進程的 Finish[i]=trueFinish[i]=trueFinish[i]=true 都滿足,則表示系統處于安全狀態;否則,系統處于不安全狀態。
??● 流程圖如下:
3.2.6 算法的實戰(樣例)
??● 題目描述:假定系統中有 5 個進程 {P0,P1,P2,P3,P4}\{P0,P1,P2,P3,P4\}{P0,P1,P2,P3,P4} 和 3 類資源 {A,B,C}\{A,B,C\}{A,B,C} 各類資源的數目分別是10、5、7。已知 T0T_0T0? 時刻資源分配情況如下:
??問題一:該系統是否是安全的?
??問題二:假設 P1P_1P1? 請求資源 Request{1,0,2}Request\{1,0,2\}Request{1,0,2},再判斷該系統是否是安全的?
??● 問題一解答:接下來我們需求出這個狀態下的安全序列,也就是將可利用的資源分配給某個 “需要資源小于可利用資源的” 進程,讓這個進程運行完成。該進程運行完成之后將會釋放資源(也就是將先前分配給該程序的資源重新添加到可利用的資源),然后再執行同樣的操作。只要能找到滿足 NeedNeedNeed 小于 AvailableAvailableAvailable ,就能分配到資源,讓該進程運行完成,最后將資源釋放。如果最后每一個進程都能運行完成,就能得到了我們的安全序列,這時該系統就是安全的。否則,不安全。
??● 執行過程:
??① 將 AvailableAvailableAvailable 和 NeedNeedNeed 對比,P0P_0P0? 的 Need>AvailableNeed>AvailableNeed>Available,不滿足,往后找。
??② AvailableAvailableAvailable 大于 P1P_1P1? 的 NeedNeedNeed,分配給 P1P_1P1?。P1P_1P1? 就能運行完成,最后釋放資源 {2,0,0}\{2,0,0\}{2,0,0} 。所以現在的資源就是 {3,3,2}+{2,0,0}={5,3,2}\{3,3,2\}+\{2,0,0\}=\{5,3,2\}{3,3,2}+{2,0,0}={5,3,2}
??③ 然后繼續向下找,P2P_2P2? 不滿足條件,P3P_3P3? 滿足條件,將資源分配給 P3P_3P3?,讓其運行完成,并釋放空間 {2,1,1}\{2,1,1\}{2,1,1},所以現在的資源就是 {5,3,2}+{2,1,1}={7,4,3}\{5,3,2\}+\{2,1,1\}=\{7,4,3\}{5,3,2}+{2,1,1}={7,4,3}
??④ 依次類推得到安全序列為 {P1,P3,P4,P2,P0}\{P1,P3,P4,P2,P0\}{P1,P3,P4,P2,P0}。過程如下圖,其中 FinishFinishFinish 表示進程運行完成。
??所以,該系統是安全的。
??● 問題二解答:首先要檢測看請求資源是不是比可利用資源、是不是比需要的資源小,如果其中一個或兩個條件都不滿足,進程等待,如果滿足進接下來的操作。這里 {1,0,2}\{1,0,2\}{1,0,2} 是滿足這兩個條件的。我們進行的操作就是將請求資源加到 AllocationAllocationAllocation 上面,也就是已分配的資源得到擴充。同樣的請求的資源一定是來自可利用資源的,所以可利用資源要減去請求資源的數目,因為 NeedNeedNeed 和 AllocationAllocationAllocation 的和是一個固定值 MaxMaxMax 所以相應的 AllocationAllocationAllocation 加上一個數值,NeedNeedNeed 就要減上一個數值,變化之后如下圖所示:
??● 然后再像前面一樣,把這個表當成T0時刻的資源分配狀態,再來找安全序列,判斷系統是不是安全的即可。
四、進程死鎖的檢測與解決
4.1 機制原理
??① 允許死鎖發生。
??② 系統不斷監視進展情況,判斷死鎖是否發生。
??③ 一旦死鎖發生則采取專門的措施,解除死鎖并以最小的代價恢復運行。
??● 檢測時機:定時檢測、進程等待時、資源利用率下降時等。
??● 檢測手段:進程-資源分配圖(如下圖所示)。
4.2 死鎖檢測
??● 檢測模型:
????① 方框表示資源類
????② 黑圓點表示資源實例
????③ 圓圈中加進程名表示進程
????④ 資源實例指向進程的一條有向邊來表示分配邊
????⑤ 進程指向資源類的一條有向邊來表示申請邊
????⑥ 檢測 “進程-資源分配圖” 是否可完全簡化
??● 檢測步驟:(執行過程如下)
????① 找一個只有分配邊的非孤立進程結點,去掉分配邊將其變為孤立結點;若找不到則轉 ③,否則轉 ②。
????② 將資源分配給一個等待資源的進程,將某進程的申請邊變為分配邊,轉 ①。
????③ 圖中有進程不是孤立結點,則此圖不可完全簡化,滿足死鎖的充分條件,系統為死鎖狀態。
4.3 死鎖解除
??● 資源剝奪法:從其他進程那里剝奪足夠數量的資源給死鎖進程,以解除死鎖狀態。
??● 撤消進程法:撤消全部死鎖進程,恢復到正常狀態,簡單但代價太大。所以一般會按照某種順序逐個撤消死鎖進程,直到有足夠的資源供其他未被撤消的進程使用,以消除死鎖狀態
五、進程死鎖問題的思考
5.1 死鎖原因
??① 系統資源不足
??② 進程運行推進的順序不合適
??③ 資源分配不當
5.2 解決原則
??① 單獨使用死鎖預防、避免、檢測與解除并不能全面解決操作系統中遇到的所有死鎖問題。
??② 可將系統中的進程、資源分為若干類,對每一類進程、資源使用最適合它的辦法解決死鎖。
六、參考附錄:
[1] 《操作系統A》
上課用的慕課
鏈接: https://www.icourse163.org/course/NJUPT-1003219004?from=searchPage.
[2] 《操作系統教程》
上課用的教材
上一篇文章地址鏈接: 【操作系統⑨】——進程間通信的概述【kill() signal() shmget() shmat() 實例 共享存儲通信 消息通信 管道通信 】.
下一篇文章地址鏈接: 【操作系統?】——存儲管理(上)【分區存儲管理 分頁存儲管理+詳細樣例】.
期末考試總復習——地址鏈接:《操作系統期末總復習——絕地求生版》.
操作系統系列文章正在更新中… ?? ??
總結
以上是生活随笔為你收集整理的【操作系统⑩】——进程死锁【银行家算法+详细样例 进程死锁的预防机制、避免机制、检测与解决】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 单元测试用例编写总结 (白盒测试)
- 下一篇: MMTW