作業系統PV操作
三態模型
程序通常分為就緒、執行和阻塞三種工作狀態。
三種狀態在某些條件下可以轉換,具體轉換關係如下:
程序三個狀態之間的轉換是通過PV操作和訊號量來控制的,其中訊號量起到了很重要的作用。
訊號量
訊號量是最早出現的用來解決程序同步與互斥問題的機制。
訊號量(Saphore)由一個值和一個指標組成,指標指向等待該訊號量的程序,訊號量的值表示相應資源的使用情況。
訊號量
S>=0
時,S
表示可用資源的數量,執行一次P操作意味著請求分配一個資源,因此S
的值減1
;訊號量
S<0
時,表示已經沒有可用資源,S
的絕對值表示當前等待該資源的程序數,請求者必須等待其他程序釋放該類資源才能繼續執行,而執行一個V操作意味著釋放一個資源,因此S
的值加1
;若
S<0
,表示有某些程序正在等待該資源,因此要喚醒一個等待狀態的程序,使之執行下去。注意,訊號量的值只能通過PV操作來改變。
兩類問題
在說明這兩類問題之前首先解釋一些相關的概念:
PV操作:一種實現程序互斥與同步的有效方法,包含P操作與V操作。
P操作:使 S=S-1
,若 S>=0
,則該程序繼續執行,否則排入等待佇列。
V操作:使 S=S+1
,若 S>0
,喚醒等待佇列中的一個程序。
臨界資源:同一時刻只允許一個程序訪問的資源,與上面所說的 S
有關聯。
緩衝區問題
程序 P1
將資訊輸入到緩衝區 B
P2
負責從緩衝區 B
中取出資料輸出,緩衝區容量為 n
。
對於程序 P1
來說,如果緩衝區滿,則應暫停輸入,等待 P2
程序取走資料後再輸入新資料;
而對於程序 P2
來說,如果緩衝區空,則應等待 P1
程序送來新資料。
我們首先分析一下,假設緩衝區未滿且有資料存在時, P2
程序可以順利的取出一個數據,同樣 P1
程序此時也可以順利的新增一個數據。
也就是說,對於這兩個程序的每一次操作,只要初始條件滿足,那麼它一定可以順利的執行下去,不會受到其他條件的制約。
於是便有:
P1() { P(empty); 輸入新資料; V(full); } P2() { P(full); 取出資料; V(empty); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
其中 empty
初始值為緩衝區容量 n
, full
初始值為 0
。
假如緩衝區為空時, P2
程序阻塞, P1
可以順利執行,隨後喚醒 P2
程序執行。
假如緩衝區為滿時, P1
程序阻塞, P2
可以順利執行,隨和喚醒 P1
程序執行。
其中的制約關係如下
公交車司機售票員問題
設公交車上司機的活動是啟動車輛,正常行車,到站停車;售票員的活動是關車門,售票,開車門,用訊號量和PV操作來實現它們的同步。
首先設訊號量 S1
、 S2
,其中:
S1
表示是否允許司機啟動汽車,初始值為 0
。
S2
表示是否允許售票員開門,初始值為 0
。
於是便有:
司機程序()
{
P(S1);
啟動車輛;
正常行駛;
到站停車;
V(S2);
}
售票員程序()
{
關車門;
V(S1);
售票;
P(S2);
開車門;
上下客;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
我們來分析一下這個過程, S1
與 S2
的初始值都為 0
。
如果售票員沒有關車門的話司機程序會阻塞在P操作之前,直到售票員關閉車門後執行V操作喚醒司機程序啟動車輛…
之後的一段時間司機程序與售票員程序可以同時執行。
當司機到站停車前售完票的售票員會阻塞在P操作之前,直到司機到站停車後執行V操作喚醒售票員開車門,然後上下客。
(那麼問題來了,如果到站停車後售票員還沒有售完票會怎麼樣呢?答案是售票員會繼續售票,直到結束以後才會開車門上下客,然後耽誤了好多乘客的時間於是被解僱了,hahah沒有那麼誇張啦~)
這便是公交車司機與售票員之間的制約關係了,如下:
總結
使用PV操作實現程序同步時應該注意的問題有:
- 同一訊號量的P、V操作要成對出現
- 訊號量的初始值與相應資源的數量有關,也與P、V操作在程式中出現的位置有關
- 我們要首先分析出程序間的制約關係,在保證程序間有正確同步關係的情況下,確定哪一個程序先執行,哪一個程序後執行,彼此間應該用什麼訊號量來協調