Linux訊號量PV操作

來源:互聯網
上載者:User

 

Linux訊號量PV操作

semop操作中:sembuf結構的sem_flg成員可以為0、IPC_NOWAIT、SEM_UNDO 。為SEM_UNDO時,它將使作業系統跟蹤當前進程對這個訊號量的修改情況,如果這個進程在沒有釋放該訊號量的情況下終止,作業系統將自動釋放該進程持有的

 semop操作中:sembuf結構的sem_flg成員可以為0、IPC_NOWAIT、SEM_UNDO 。為SEM_UNDO時,它將使作業系統跟蹤當前進程對這個訊號量的修改情況,如果這個進程在沒有釋放該訊號量的情況下終止,作業系統將自動釋放該進程持有的訊號量。除非你對訊號量的行為有特殊的要求,否則應該養成設定sem_flg為SEM_UNDO的好習慣。

   1:  //假設兩個進程(父子進程)對一個檔案進行寫操作,但是這個檔案同一時間只能有一個進程進行寫操作。

   2:  //利用訊號量實現pv操作

   3:  #include <stdio.h>

   4:  #include <stdlib.h>

   5:  #include <sys/ipc.h>

   6:  #include <sys/sem.h>

   7:  #include <sys/types.h>

   8:  #include <fcntl.h>

   9:  struct sembuf sops;

  10:  static int sid;

  11:  //建立一個新的訊號量集

  12:  int createSemset(void)

  13:  {

  14:  char* pathname="semset";

  15:  if( access(pathname, F_OK)!=0 )

  16:  {

  17:  int fd=open(pathname, O_RDWR | O_CREAT, 0666);   

  18:  if( fd<0 )

  19:  {

  20:  perror("open");

  21:  return -1;

  22:  }

  23:  }

  24:  key_t key=ftok(pathname, 'a');

  25:  if( -1==key )

  26:  {

  27:  perror("ftok");

  28:  return -1;

  29:  }

  30:  return semget(key, 1, IPC_CREAT | 0666) ;

  31:  }

  32:  

  33:  //P操作

  34:  int P(void)

  35:  {

  36:  sops.sem_num=0;

  37:  sops.sem_op=-1;

  38:  sops.sem_flg=0;

  39:  return semop(sid, &sops, 1);

  40:  }

  41:  //V操作

  42:  int V(void)

  43:  {

  44:  sops.sem_num=0;

  45:  sops.sem_op=1;

  46:  sops.sem_flg=0;

  47:  return semop(sid, &sops, 1);

  48:  }

  49:  int main(int argc, char *argv[])

  50:  {

  51:  sid=createSemset();

  52:  if( -1==sid )

  53:  {

  54:  perror("createSemset");

  55:  exit(1);

  56:  }

  57:  

  58:  if( -1==semctl(sid, 0, SETVAL, 1) )

  59:  {

  60:  perror("SETVAL");

  61:  exit(1);

  62:  }

  63:  pid_t pid=fork();

  64:  if( pid<0 )

  65:  {

  66:  perror("fork");

  67:  exit(1);

  68:  }

  69:  else if( 0==pid )

  70:  {

  71:  while(1)

  72:  {

  73:  if( -1==P() )

  74:  {

  75:  printf("P操作失敗!

");   

  76:  exit(1);

  77:  }

  78:  printf("子進程正在對檔案進行寫操作!

");

  79:  sleep(1);   

  80:  printf("子進程寫操作完畢,釋放資源!

");

  81:  if( -1==V() )

  82:  {

  83:  printf("V操作失敗!");

  84:  exit(1);

  85:  }

  86:  }

  87:  }

  88:  else

  89:  {

  90:  while(1)

  91:  {

  92:  if( -1==P() )

  93:  {

  94:  printf("P操作失敗!

");   

  95:  exit(1);

  96:  }

  97:  printf("父進程進程正在對檔案進行寫操作!

");   

  98:  sleep(1);

  99:  printf("父進程寫操作完畢,釋放資源!

");

 100:  if( -1==V() )

 101:  {

 102:  printf("V操作失敗!");

 103:  exit(1);

 104:  } ......

   1:  void P(int semid)

   2:  {

   3:      struct sembuf sem_p;

   4:      sem_p.sem_num = 0;

   5:      sem_p.sem_op = -1;

   6:      sem_p.sem_flg = SEM_UNDO;

   7:      if (semop(semid, &sem_p, 1) == -1) {

   8:          perror("p op failed

");

   9:          exit(1);

  10:      }

  11:  }

  12:  

  13:  void V(int semid)

  14:  {

  15:      struct sembuf sem_p;

  16:      sem_p.sem_num = 0;

  17:      sem_p.sem_op = 1;

  18:      sem_p.sem_flg = SEM_UNDO;

  19:      if (semop(semid, &sem_p, 1) == -1) {

  20:          perror("v op failed

");

  21:          exit(1);

  22:      }

  23:  }

PV原語通過操作訊號量來處理進程間的同步與互斥的問題。其核心就是一段不可分割不可中斷的程式。

 

訊號量的概念1965年由著名的荷蘭電腦科學家Dijkstra提出,其基本思路是用一種新的變數類型(semaphore)來記錄當前可用資源的數量。有兩種實現方式:1)semaphore的取值必須大於或等於0。0表示當前已沒有空閑資源,而正數表示當前空閑資源的數量;2)semaphore的取值可正可負,負數的絕對值表示正在等待進入臨界區的進程個數。

 

訊號量是由作業系統來維護的,使用者進程只能通過初始化和兩個標準原語(P、V原語)來訪問。初始化可指定一個非負整數,即空閑資源總數。

 

P原語:P是荷蘭語Proberen(測試)的首字母。為阻塞原語,負責把當前進程由運行狀態轉換為阻塞狀態,直到另外一個進程喚醒它。操作為:申請一個空閑資源(把訊號量減1),若成功,則退出;若失敗,則該進程被阻塞;

 

V原語:V是荷蘭語Verhogen(增加)的首字母。為喚醒原語,負責把一個被阻塞的進程喚醒,它有一個參數表,存放著等待被喚醒的進程資訊。操作為:釋放一個被佔用的資源(把訊號量加1),如果發現有被阻塞的進程,則選擇一個喚醒之。

 

具體PV原語對訊號量的操作可以分為三種情況:

 

1)把訊號量視為一個加鎖標誌位,實現對一個共用變數的互斥訪問。

 

實現過程:

 

P(mutex); // mutex的初始值為1 訪問該共用資料;

 

V(mutex);

 

非臨界區

 

2)把訊號量視為是某種類型的共用資源的剩餘個數,實現對一類共用資源的訪問。

 

實現過程:

 

P(resource); // resource的初始值為該資源的個數N 使用該資源;

 

V(resource); 非臨界區

 

3)把訊號量作為進程間的同步工具

 

實現過程:

 

臨界區C1;

 

P(S);

 

V(S);

 

臨界區C2;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.