信號量中的PV操作

一、信號量的概念

    1、信號量的類型定義
    信號量(semaphore)的數據結構爲一個值和一個指針,指針指向等待該信號量的下一個進程。信號量的值與相應資源的使用情況有關。當它的值大於0時,表示當前可用資源的數量;當它的值小於0時,其絕對值表示等待使用該資源的進程個數。注意,信號量的值僅能由PV操作來改變。

    一般來說,信號量S>=0時,S表示可用資源的數量。執行一次P操作意味着請求分配一個單位資源,因此S的值減1;當S<0時,表示已經沒有可用資源,請求者必須等待別的進程釋放該類資源,它才能運行下去。而執行一個V操作意味着釋放一個單位資源,因此S的值加1;若S<0,表示有某些進程正在等待該資源,因此要喚醒一個等待狀態的進程,使之運行下去。
    2、PV原語
    PV操作是典型的同步機制之一。用一個信號量與一個消 息聯繫起來,當信 號量的值爲0時,表示期 望的消息尚未產生;當信號 量的值非0時,表示期望的消息已經存在。用P V操作實現進程同步時,調用P操作測試消息是否到達,調用V操作發送消息。
    對一個信號量變量可以進行兩種原語操作:p操作和v操作,定義如下:

procedure p(var s:samephore);
{
     s.value=s.value-1;
     if (s.value<0)
          asleep(s.queue);
}
procedure v(var s:samephore);
{
     s.value=s.value+1;
     if (s.value<=0)
          wakeup(s.queue);
}
    其中用到兩個標準過程:
    asleep(s.queue);執行此操作的進程的PCB進入s.queue尾部,進程變成等待狀態
    wakeup(s.queue);將s.queue頭進程喚醒插入就緒隊列
    s.value初值爲1時,可以用來實現進程的互斥。
    P操作和V操作是不可中斷的程序段,稱爲原語。如果將信號量看作共享變量,則PV操作爲其臨界區,多個進程不能同時執行,一般用硬件方法保證。一個信號量只能置一次初值,以後只能對之進行P操作或V操作。

    由此也可以看到,信號量機制必須有公共內存,不能用於分佈式操作系統,這是它最大的弱點。
    V原語的主要操作是:
    (1)sem加1;
    (2)若相加結果大於零,則進程繼續執行;
    (3)若相加結果小於或等於零,則喚醒一阻塞在該信號量上的進程,然後再返回原進程繼續執行或轉進程調度。

    3、使用PV操作實現進程互斥時應該注意的是:
    (1)每個程序中用戶實現互斥的P、V操作必須成對出現,先做P操作,進臨界區,後做V操作,出臨界區。若有多個分支,要認真檢查其成對性。
    (2)P、V操作應分別緊靠臨界區的頭尾部,臨界區的代碼應儘可能短,不能有死循環。
    (3)互斥信號量的初值一般爲1。
    利用信號量和PV操作實現進程同步:
    PV操作是典型的同步機制之一。用一個信號量與一個消息聯繫起來,當信號量的值爲0時,表示期望的消息尚未產生;當信號量的值非0時,表示期望的消息已經存在。用PV操作實現進程同步時,調用P操作測試消息是否到達,調用V操作發送消息。
    4、使用PV操作實現進程同步時應該注意的是:
    (1)分析進程間的制約關係,確定信號量種類。在保持進程間有正確的同步關係情況下,哪個進程先執行,哪些進程後執行,彼此間通過什麼資源(信號量)進行協調,從而明確要設置哪些信號量。
    (2)信號量的初值與相應資源的數量有關,也與P、V操作在程序代碼中出現的位置有關。
    (3)同一信號量的P、V操作要成對出現,但它們分別在不同的進程代碼中。

二、對PV操作的一些理解偏差

    五個問題:
    1、以V原語的1、2步來做,Sem不就永遠大於0,那進程不就一直循環執行成爲死循環了?
    2、Sem大於0那就表示有臨界資源可供使用,爲什麼不喚醒進程?
    3、Sem小於0應該是說沒有臨界資源可供使用,爲什麼還要喚醒進程?

    4、如果是互斥信號量的話,應該設置信號量Sem=1,但是當有5個進程都訪問的話,最後在該信號量的鏈表裏會有4個在等待,也是說S=-4,那麼第一個進程執行了V操作使S加1,釋放了資源,下一個應該能夠執行,但喚醒的這個進程在執行P操作時因S<0,也還是執行不了,這是怎麼回事呢?
    5、Sem的絕對值表示等待的進程數,同時又表示臨界資源,這到底是怎麼回事?
    解析:
    1、P操作對sem減1的。P、V原語必須成對使用!從而不會造成死循環。
    2、Sem大於0的確表示有臨界資源可供使用,而且這個時候沒有進程被阻塞在這個資源上,也就是說沒有進程因爲得不到這類資源而阻塞,所以沒有被阻塞的進程,自然不需要喚醒。
    3、V原語操作的本質在於:一個進程使用完臨界資源後,釋放臨界資源,使Sem加1,以通知其它的進程,這個時候如果Sem<0,表明有進程阻塞在該類資源上,因此要從阻塞隊列裏喚醒一個進程來“轉手”該類資源。比如,有兩個某類資源,四個進程A、B、C、D要用該類資源,最開始Sem=2,當A進入,Sem=1,當B進入Sem=0,表明該類資源剛好用完, 當C進入時Sem=-1,表明有一個進程被阻塞了,D進入,Sem=-2。當A用完該類資源時,進行V操作,Sem=-1,釋放該類資源,而這時Sem<0,表明有進程阻塞在該類資源上,於是喚醒一個。
    4、當一個進程阻塞了的時候,它已經執行過了P操作,並卡在臨界區那個地方。當喚醒它時就立即進入它自己的臨界區,並不需要執行P操作了,當執行完了臨界區的程序後,就執行V操作。
    5、當信號量Sem小於0時,其絕對值表示系統中因請求該類資源而被阻塞的進程數目S大於0時表示可用的臨界資源數。注意在不同情況下所表達的含義不一樣。當等於0時,表示剛好用完。

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