回覆列表
  • 1 # 使用者2458114238191884

    在作業系統理論中有一個非常重要的概念叫做P,V原語。在我們研究程序間的互斥的時候經常會引入這個概念,將P,V操作方法與加鎖的方法相比較,來解決程序間的互斥問題。實際上,他的應用範圍很廣,他不但可以解決程序管理當中的互斥問題,而且我們還可以利用此方法解決程序同步與程序通訊的問題。

    [一]P,V原語理論

    闡述P,V原語的理論不得不提到的一個人便是赫赫有名的荷蘭科學家E.W.Dijkstra。如果你對這位科學家沒有什麼印象的話,提起解決圖論中最短路徑問題的Dijkstra演算法應當是我們再熟悉不過的了。P,V原語的概念以及P,V操作當中需要使用到的訊號量的概念都是由他在1965年提出的。

    訊號量是最早出現的用來解決程序同步與互斥問題的機制,包括一個稱為訊號量的變數及對它進行的兩個原語操作。訊號量為一個整數,我們設這個訊號量為:sem。很顯然,我們規定在sem大於等於零的時候代表可供併發程序使用的資源實體數,sem小於零的時候,表示正在等待使用臨界區的程序的個數。根據這個原則,在給訊號量附初值的時候,我們顯然就要設初值大於零。

    p操作和v操作是不可中斷的程式段,稱為原語。P,V原語中P是荷蘭語的Passeren,相當於英文的pass, V是荷蘭語的Verhoog,相當於英文中的incremnet。

    P原語操作的動作是:

    (1) sem減1;

    (2) 若sem減1後仍大於或等於零,則程序繼續執行;

    (3) 若sem減1後小於零,則該程序被阻塞後進入與該訊號相對應的佇列中,然後轉程序排程。

    V原語操作的動作是:

    (1) sem加1;

    (2) 若相加結果大於零,則程序繼續執行;

    (3) 若相加結果小於或等於零,則從該訊號的等待佇列中喚醒一等待程序,然後再返回原程序繼續執行或轉程序排程。

    需要提醒大家一點就是P,V操作對於每一個程序來說,都只能進行一次。而且必須成對使用。且在P,V願語執行期間不允許有中斷的發生。

    對於具體的實現,方法非常多,可以用硬體實現,也可以用軟體實現。我們採用如下的定義:

    procedure p(var s:samephore);

    {

    s.value=s.value-1;

    if (s.value

    }

    procedure v(var s:samephore);

    {

    s.value=s.value+1;

    if (s.value

    }

    其中用到兩個標準過程:

    asleep(s.queue);執行此操作的程序控制塊進入s.queue尾部,程序變成等待狀態

    wakeup(s.queue);將s.queue頭程序喚醒插入就緒佇列

    對於這個過程,s.value初值為1時,用來實現程序的互斥。

    雖軟說訊號量機制畢加鎖方法要好得多,但是也不是說它沒有任何的缺陷。由此我們也可以清晰地看到,這種訊號量機制必須有公共記憶體,不能用於分散式作業系統,這是它最大的弱點。

    [二]P,V原語的應用

    正如我們在文中最開始的時候提到的,P,V原語不但可以解決程序管理當中的互斥問題,而且我們還可以利用此方法解決程序同步與程序通訊的問題。

    (1)用P V原語實現程序互斥

    把臨界區置於P(sem) 和V(sem)之間。當一個程序想要進入臨界區時,它必須先執行P原語操作以將訊號量sem減1,在程序完成對臨界區的操作後,它必須執行V原語操作以釋放它所佔用的臨界區。從而就實現了程序的互斥:

    具體的過程我們可以簡單的描述如下:

    PA:

    P(sem)

    V(sem)

    PB:

    P(sem)

    V(sem)

    (2) 用P V原語實現程序同步

    程序同步問題的解決同樣可以採用這種操作來解決,我們假設兩個程序需要同步進行,一個程序是計算程序,另一個程序是列印程序,那麼這個時候兩個程序的定義可以表示為:

    PC(表示計算程序)

    A: local buf

    repeat

    buf=buf

    until buf=空

    計算

    得到計算結果

    buf=計算結果

    goto A

    PP:(表示列印程序)

    B: local pri

    repeat

    pri=buf

    until pri!=空

    列印buf中的資料

    清除buf中的資料

    goto B

    相應用P,V原語的實現過程為:

    PA: deposit(data)

    Begin local x

    P(bufempty)

    按FIFO方式選擇一個空緩衝區buf(x)

    buf(x)=data

    buf(x)置滿標記

    V(buffull)

    end

    PB:remove(data)

    Begin local x

    P(buffull)

    按FIFO方式選擇一個裝滿

    資料的緩衝區buf(x)

    data=buf(x)

    buf(x)置空標記

    V(bufempty)

    end

    (3)用P V原語實現程序通訊

    我們以郵箱通訊為例說明問題:

    郵箱通訊滿足的條件是:

    ;傳送程序傳送訊息的時候,郵箱中至少要有一個空格能存放該訊息。

    ;接收程序接收訊息時,郵箱中至少要有一個訊息存在。

    傳送程序和接收程序我們可以進行如下的描述:

    Deposit(m)為傳送程序,接收程序是remove(m). Fromnum為傳送程序的私用訊號量,信箱空格數n。mesnum為接收程序的私用訊號量,初值為0.

    Deposit(m):

    Begin local x

    P(fromnum)

    選擇空格x

    將訊息m放入空格x中

    置格x的標誌為滿

    V(mesnum)

    end

    Remove(m)

    Begin local x

    P(mesnum)

    選擇滿格x

    把滿格x中的訊息取出放m中

    置格x標誌為空

    V(fromnum)

    end

  • 中秋節和大豐收的關聯?
  • 白菜油豆腐的家常做法?