1. 程式人生 > >作業系統清華大學版筆記(十一)死鎖、銀行家演算法和程序間通訊(直接通訊、間接通訊)

作業系統清華大學版筆記(十一)死鎖、銀行家演算法和程序間通訊(直接通訊、間接通訊)

死鎖、死鎖模型、死鎖預防和恢復、銀行家演算法

死鎖:一組阻塞的程序(兩個或多個),持有一種資源,等待獲取另一個程序所佔有的資源,而導致誰都無法執行。
這裡寫圖片描述
由於程序的併發執行引起了死鎖。

死鎖模型
資源型別很多,比如CPU cycles , memory space , I/O devices,某個程序執行中的共享變數
資源個數可以有n個
每個程序可以怎麼使用資源:

  • request/get ——-free resource
  • use/hold ————requested/used resource, other processes cannot get
  • release ———–free resource

可重複使用的資源:

  • 在一個時間只能一個程序使用,且不能被刪除。OS避免殺死擁有資源的程序。
  • 程序使用資源後要釋放,讓其他程序重用
  • 有物理資源(cpu, I/O通道,主和副儲存器),也有抽象的資源(裝置和資料結構,如檔案,資料庫和訊號量)
  • 如果每個程序擁有一個資源並請求其他資源,可能導致死鎖

怎麼使用資源?
建立,銷燬—記憶體管理單元
I/O緩衝區的中斷,訊號,訊息,資訊
如果接受資訊阻塞可能會發生死鎖
少見的組合事件可能會引起死鎖

如何表述資源的分配?
資源分配圖,頂點V和邊E的集合
V有兩種
P={P1, P2…Pn } 所有程序
R={R1, R2… Rm} 所有資源型別
Requesting/claiming edge –directed edge Pi→Rj
Assignment/holding edge –directed edge Rj→Pi
這裡寫圖片描述

這裡寫圖片描述這裡寫圖片描述
左圖沒有死鎖,右圖死鎖,死鎖會有閉環出現
但有閉環出現不一定會死鎖,因為資源是迴圈的
這裡寫圖片描述
如果不包含閉環—>沒有死鎖
如果包括閉環,且每個資源類只有一個例項-→死鎖 ;否則,不會。

死鎖的特徵 : 四個的必要條件

  • 互斥
  • 持有並等待
  • 無搶佔,一個資源只能被程序自願釋放
  • 迴圈等待,形成閉環

死鎖處理的辦法
約束遞減
死鎖預防dead-lock prevention
打破死鎖出現的條件
互斥—佔用非共享資源 會增加不確定性 不推薦
佔用並等待—保證當一個程序請求資源時,不持有任何其他的資源
all or nothing 需要程序請求並分配其所有資源,資源利用率低,可能飢餓
無搶佔—允許搶佔佔有某些資源的程序
迴圈等待—對所有資源型別進行排序,並要求每個程序按照資源的順序進行申請,會出現資源利用不夠

死鎖避免 deadlock avoidance
當程序執行過程中,根據申請資源的情況判斷會不會死鎖,如果會就不給資源。
需要系統具有一些先驗資訊。
最簡單有效就是要求每個程序宣告它需要的每個型別資源的最大數目,資源在分配中根據最大數目限定提供與分配的資源數目,死鎖避免演算法要動態檢查資源的分配狀態來避免環形等待。
環形等待不一定會死鎖。分為安全狀態,不安全狀態,死鎖狀態,不安全狀態包括死鎖。
當一個程序請求可用資源,系統必須判斷分配資源是否能讓系統處於安全狀態。
安全狀態:針對所有程序,存在安全的時間序列。第一個P1結束,第二個P2結束。。。都能得到滿足,正常結束。則稱序列< P1, P2…Pn >是安全的:針對每一個程序Pi,它要求的資源能夠由當前可用的資源+所有i之前的程序所持有的資源來滿足。
程序會相繼結束,Pi只能用它之前的程序的資源。
如果Pi資源的需求不是立即可用,那麼Pi可以等到所有Pj完成。
當Pi完成後Pi+1得到所需要的資源,執行,釋放資源,並終止。

如果系統處於安全狀態 => 沒有死鎖
如果處於不安全狀態 => 可能死鎖
避免死鎖: 確保系統永遠不會進入不安全狀態

這裡寫圖片描述

銀行家演算法 DIJ設計的
有多個資源例項
每個程序必須能最大限度地利用資源
一個程序請求一個資源時,不得不等待
所有資源都必須在一段有效時間釋放
找到理想執行時序,找到就認為是安全的

這裡寫圖片描述

資料結構 n=程序數量 m=資源型別數量 不是例項
Max 總需求量 n*m矩陣 max[i, j]=k 程序Pi最多需要資源型別Rj的k個例項
Available 剩餘空閒量 長度為m的向量,如果available[j]=k 則有k個型別Rj的資源例項可用
Allocation 已分配量 n*m矩陣 allocation[I, j]=k 程序Pi已經分配了資源型別Rj的k個例項
Need 未來需要量 n*m矩陣 need[i, j]=k 程序Pi可能需要資源型別Rj的k個例項
Max[i, j]=need[I,j]+allocation[i,j]

這裡寫圖片描述
Finish [i] 得到了所有資源,可以執行結束
看哪個未結束的程序的need小於avaliable,就是第一個結束的程序,結束後釋放資源,重複。
這裡寫圖片描述

死鎖檢測deadlock detection

也是銀行家演算法,由於開銷大,且需要一開始就知道max[i,j],不一定能得到,所以主要用於開發階段的除錯,不會用於檢測,特別是單一OS時

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

死鎖恢復recovery from deadlock
通過殺死所有死鎖程序,在一個時間內終止一個程序直到死鎖消除等方式完成,都干擾了程序的正常執行,都有強制性。
多數情況下,就是重啟。
資源搶佔,打破4個條件。
以最小的成本選擇一個受害者
程序的優先順序,執行時間,還需多少時間,佔用的資源,完成需要的資源(max),多少程序需要被終止,程序是互動還是批處理
重啟程序,返回到安全狀態—回滾
同一程序可能一直被選為受害者,包括回滾的數量—飢餓
確保不會死鎖,執行系統進入死鎖然後恢復
假裝不知道死鎖,不佔了就重啟(死鎖恢復):用於大多數作業系統,包括UNIX,主要是因為開銷大,為了避免死鎖設定條件會降低OS的效能

11-2 IPC: inter process communication 程序間通訊

程序通訊的機制及同步
不使用共享變數的程序通訊
IPC facility 提供2個操作:
send(message) - 訊息大小固定/可變
receive (message)

如果P和Q想通訊,需要:
在它們之間建立通訊鏈路
通過send/receive交換訊息

通訊鏈路的實現
物理(例如,共享記憶體,硬體匯流排)
邏輯(如邏輯屬性)

程序要相互獨立,但另一方面也要相互協作
傳送訊息,接收訊息
這裡寫圖片描述
左側程序A和B是間接的通訊,右側是直接通訊

直接通訊
為了實現直接通訊,要有傳送和接收的ID
程序必須正確地命名對方
send( P, message) - 傳送資訊到程序P
通訊鏈路的屬性
自動建立鏈路
一條鏈路恰好對應一對通訊程序
每對程序之間只有一個連結存在
連結可以是單向的,但通常為雙向的

間接通訊
為了實現間接通訊,要傳送到共享區,傳送方和接收方都不關注具體的另一方是誰
定向從訊息佇列接收訊息:
每個訊息佇列都有一個唯一的ID
只有他們共享了一個訊息佇列,程序才能通訊
通訊鏈路的屬性:
只有程序共享一個共同的訊息佇列,才建立鏈路
連結可以與許多程序相關聯
每對程序可以共享多個通訊鏈路
連線可以是單向或者雙向
操作:
建立一個新的訊息佇列
通過訊息佇列傳送和接收訊息
銷燬訊息佇列
原語的定義如下:
send(A, message) – 傳送訊息到佇列A
receive(A, message) - 從佇列A接受訊息

另一方面,可以分為阻塞,非阻塞
阻塞被認為是同步的
blocking send has the sender block until the message is received
blocking receive has the receiver block until a message is available
非阻塞被認為是非同步的
non-blocking send has the sender send the message and continue
non-blocking receive has the receiver receive a valid message or null

通訊鏈路緩衝:
佇列的訊息被附加到鏈路的3種方式
0容量—0 messages 傳送方必須等待接收方
有限容量—n messages 的有限長度,傳送方在佇列滿的時候要等待
無限容量—理想狀況,不用等

ipc常用手段:訊號,管道,訊息佇列,共享記憶體
訊號:
硬體中斷interrupt,訊號是軟體中斷,通知有事件要處理
應用程式會catch,預設,停下來處理訊號,特殊處理函式。

examples: SIGFPE, SIGKILL, SIGUSRI, SIGSTOP, SIGCONT
接收到訊號時會發生什麼
catch : 指定訊號處理函式被呼叫
ignore: 依靠作業系統的預設操作 , 如abort, memory dump, suspend or resume process
mask: 閉塞訊號因此不會傳送(可能是暫時的,當處理同樣型別的訊號)
不足:不能傳輸要交換的任何資料
效率很高,非同步。一般處理完後會回到被打斷的程序。

過程:
這裡寫圖片描述
第二步,改入口,OS把系統呼叫返回的堆疊修改到訊號處理函式的入口,再把訊號處理函式結束後的地址處理成原有程序中斷點的入口。
木馬程式會改堆疊

管道:用於資料交換,與訊號不同。理解為記憶體中的一個buffer
子程序從父程序繼承包括檔案描述符等的資源。File descriptor 0stdin, 1 stdout, 2 stderr
UNIX想靈活組合小程式,一個的輸出是另一個的輸入,用豎線|來表示
把ls的輸出stdout重定向,通過一個類似buffer的管道作為stdin傳輸給more。More以為是從i/o給它的,實際是ls給它的。程序不關心。
這裡寫圖片描述

完成分頁顯示目錄的功能
buffer是有限的,滿了會阻塞,如果ls太慢也會sleep
能協作的基礎是有shell,shell會建立一個管道,為ls建立程序,設定stdout為管道寫端,對more同理。管道以檔案的形式存在。
訊息佇列:
管道必須有父程序,資料是位元組流,沒有資料結構。訊息佇列可以多個不相干的程序來傳遞資料,而且message作為一個位元組序列儲存,message quenues是訊息陣列。是一個有意義的結構化。
按FIFO/FILO管理
這裡寫圖片描述
有Buffer限制

共享記憶體:
直接的方式。不用系統呼叫send&receive,資料量最大,最快。
開始要建立共享區域。方便,高效,沒有多餘的拷貝。
每個程序都有私有地址空間,其中明確地設定了共享記憶體段。同一塊實體記憶體對映到不同的地址空間中去。頁表。。。
但必須同步資料訪問。寫的時候要上鎖。同步互斥。
這裡寫圖片描述
Linux Unix中常見
Socket機制。