1. 程式人生 > >PV操作

PV操作

搬運工 系統 del 幫助 int 而且 情況 是否 編號

PV操作的含義

  PV操作由P操作原語和V操作原語組成(原語是不可中斷的過程),對信號量進行操作,具體定義如下:
 P(S):①將信號量S的值減1,即S=S-1;
   ②如果S>=0,則該進程繼續執行;否則該進程置為等待狀態,排入等待隊列。
V(S):①將信號量S的值加1,即S=S+1;
   ②如果S>0,則該進程繼續執行;否則釋放隊列中第一個等待信號量的進程。
PV操作的意義
:我們用信號量及PV操作來實現進程的同步和互斥。PV操作屬於進程的低級通信。

什麽是信號量?

  信號量(semaphore)的數據結構為一個值和一個指針,指針指向等待該信號量的下一個進程。

信號量的值與相應資源的使用情況有關。當它的值大於0時,表示當前可用資源的數量;當它的值小於0時,其絕對值表示等待使用該資源的進程個數。註意,信號量的值僅能由PV操作來改變。
一般來說,信號量S>=0時,S表示可用資源的數量。執行一次P操作意味著請求分配一個單位資源,因此S的值減1;當S<0時,表示已經沒有可用資源,請求者必須等待別的進程釋放該類資源,它才能運行下去。而執行一個V操作意味著釋放一個單位資源,因此S的值加1;若S<=0,表示有某些進程正在等待該資源,因此要喚醒一個等待狀態的進程,使之運行下去。

利用信號量和PV操作實現進程互斥的一般模型是:
  進程P1 進程P2 …… 進程

Pn
  …… …… ……
  P(S); P(S); P(S);

  臨界區; 臨界區; 臨界區;
  V(S); V(S); V(S);
  …… …… …… ……

其中信號量S用於互斥,初值為1。

 臨界區:就是進程訪問臨界資源的那段代碼。


使用PV操作實現進程互斥時應該註意的是:
(1)每個程序中用戶實現互斥的P、V操作必須成對出現,先做P操作,進臨界區,後做V操作,出臨界區。若有多個分支,要認真檢查其成對性。
(2)P、V操作應分別緊靠臨界區的頭尾部,臨界區的代碼應盡可能短,不能有死循環。
(3)互斥信號量的初值一般為1。

利用信號量和PV操作實現進程同步

  下面是一張同步的圖:

  技術分享

  這張圖也特別的形象具體,我們具體來看看這張圖,A倉庫有貨物,然後我們需要把貨物搬運到B倉庫,由搬運工甲和搬運工乙來完成這個過程;那麽他們的目標就只有一個,就是把貨物從A搬到B去,共同奔著這個方向去發展,所以我們說這是一個同步的問題。

  PV操作是典型的同步機制之一。用一個信號量與一個消息聯系起來,當信號量的值為0時,表示期望的消息尚未產生;當信號量的值非0時,表示期望的消息已經存在。用PV操作實現進程同步時,調用P操作測試消息是否到達,調用V操作發送消息。
使用PV操作實現進程同步時應該註意的是:

(1)分析進程間的制約關系,確定信號量種類。在保持進程間有正確的同步關系情況下,哪個進程先執行,哪些進程後執行,彼此間通過什麽資源(信號量)進行協調,從而明確要設置哪些信號量。
(2)信號量的初值與相應資源的數量有關,也與P、V操作在程序代碼中出現的位置有關。
(3)同一信號量的P、V操作要成對出現,但它們分別在不同的進程代碼中。

示例

【例1】生產者-消費者問題

  在多道程序環境下,進程同步是一個十分重要又令人感興趣的問題,而生產者-消費者問題是其中一個有代表性的進程同步問題。下面我們給出了各種情況下的生產者-消費者問題,深入地分析和透徹地理解這個例子,對於全面解決操作系統內的同步、互斥問題將有很大幫助。

  (1)一個生產者,一個消費者,公用一個緩沖區。
    定義兩個同步信號量:
      empty——表示緩沖區是否為空,初值為1
     full——表示緩沖區中是否為滿,初值為0。
    生產者進程
      while(TRUE){
        生產一個產品;
       P(empty);
       產品送往Buffer;
       V(full);
      }

    消費者進程
      while(True){
        P(full);

        從Buffer取出一個產品;
       V(empty);
       消費該產品;
     }
  (2)一個生產者,一個消費者,公用n個環形緩沖區。
    定義兩個同步信號量:
      empty——表示緩沖區是否為空,初值為n。
      full——表示緩沖區中是否為滿,初值為0。

    設緩沖區的編號為1~n-1,定義兩個指針in和out,分別是生產者進程和消費者進程使用的指,指向下一個可用的緩沖區。

  生產者進程
    while(TRUE){
    生產一個產品;
    P(empty);
    產品送往buffer(in);
    in=(in+1)mod n
    V(full);
  }

  消費者進程
    while(TRUE){
     P(full);
     從buffer(out)中取出產品;
     out=(out+1)mod n
     V(empty);
    消費該產品;
   }
3)一組生產者,一組消費者,公用n個環形緩沖區
 在這個問題中,不僅生產者與消費者之間要同步,而且各個生產者之間、各個消費者之間還必須互斥地訪問緩沖區。

  定義四個信號量:
    empty——表示緩沖區是否為空,初值為n。
    full——表示緩沖區中是否為滿,初值為0。
    mutex1——生產者之間的互斥信號量,初值為1。
    mutex2——消費者之間的互斥信號量,初值為1。

設緩沖區的編號為1~n-1,定義兩個指針in和out,分別是生產者進程和消費者進程使用的指針,指向下一個可用的緩沖區。
  生產者進程
    while(TRUE){
    生產一個產品;
    P(empty);
    P(mutex1)
    產品送往buffer(in);
    in=(in+1)mod n
    V(mutex1);
     V(full);
    }

  消費者進程
    while(TRUE){

     P(full)
    P(mutex2)

     從buffer(out)中取出產品;
    out=(out+1)mod n
    V(mutex2);
     V(empty);
     消費該產品;
   }
  需要註意的是無論在生產者進程中還是在消費者進程中,兩個P操作的次序不能顛倒。應先執行同步信號量的P操作,然後再執行互斥信號量的P操作,否則可能造成進程死鎖。

【例2】桌上有一空盤,允許存放一只水果。爸爸可向盤中放蘋果,也可向盤中放桔子,兒子專等吃盤中的桔子,女兒專等吃盤中的蘋果。規定當盤空時一次只能放一只水果供吃者取用,請用P、V原語實現爸爸、兒子、女兒三個並發進程的同步。

分析 在本題中,爸爸、兒子、女兒共用一個盤子,盤中一次只能放一個水果。當盤子為空時,爸爸可將一個水果放入果盤中。若放入果盤中的是桔子,則允許兒子吃,女兒必須等待;若放入果盤中的是蘋果,則允許女兒吃,兒子必須等待。本題實際上是生產者-消費者問題的一種變形。這裏,生產者放入緩沖區的產品有兩類,消費者也有兩類,每類消費者只消費其中固定的一類產品。

:在本題中,應設置三個信號量S、So、Sa,信號量S表示盤子是否為空,其初值為l;信號量So表示盤中是否有桔子,其初值為0;信號量Sa表示盤中是否有蘋果,其初值為0。同步描述如下:
int S1;
int Sa=
0;
int So=0;

main()
{
cobegin
father(); /*父親進程*/
son(); /*兒子進程*/
daughter(); /*女兒進程*/
coend

father()
{
while(1)
{
P(S);
將水果放入盤中;
if(放入的是桔子)V(So);
else V(Sa);
}
}
son()
{
while(1)
{
P(So);
從盤中取出桔子;
V(S);
吃桔子;

}
daughter()
{
while(1)
{
P(Sa);
從盤中取出蘋果;
V(S);
吃蘋果;

PV操作