linux進程間通信--信號量

信號量集函數


查看創建的信號量:ipcs -s
刪除創建的信號量:ipcrm -S key

1.創建信號量集


semget函數:

  int semget(key_t key, //id
             int nsems,//信號量集中有幾個信號量  打開寫0
             int semflg);//IPC_CREAT|0644 打開0

代碼實現爲:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <sys/ipc.h>
  5 #include <sys/sem.h>
  6 #include <unistd.h>
  7 
  8 //創建信號量集
  9 
 10 int main()
 11 {
 12     int id=semget(1234,1,IPC_CREAT|0644);
 13     if(id==-1)
 14         perror("semget"),exit(1);
 15 
 16     printf("create ok!\n");
 17 }

這裏寫圖片描述

2.設置初值


semctl函數:

union semun {
            int  val; /* Value for SETVAL */  
            };

int semctl(int semid, //id
          int semnum,//給第幾個信號量的賦值
           int cmd,//SETVAL
           ...);

返回值:當前信號量的值

代碼實現爲:
setval.c

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <sys/ipc.h>
  4 #include <sys/sem.h>
  5 #include <stdlib.h>
  6 
  7 
  8 union semun
  9 {
 10     int val;
 11 };
 12 
 13 int main()
 14 {
 15     int id=semget(1234,0,0);//打開信號量集填0
 16     if(id==-1)
 17         perror("semget"),exit(1);
 18 
 19     union semun su;//聯合體變量
 20     su.val=10;
 21     semctl(id,0,SETVAL,su);//設置初值
 22 }

3.獲得信號量的值


int semctl(int semid, //id
          int semnum,//想獲得第幾個信號量的值
          int cmd);//GETVAL
返回值:當前信號量的值

getval.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <sys/ipc.h>
  4 #include <sys/sem.h>
  5 
  6 int main(void)
  7 {
  8     int id=semget(1234,0,0);
  9     if(id==-1)
 10         perror("semget"),exit(1);
 11     int ret=semctl(id,0,GETVAL);//獲取第幾個信號量的初值
 12     printf("val=%d\n",ret);
 13 }

2與3結果如下:
這裏寫圖片描述

4.PV操作


semop函數:

struct sembuf{
        unsigned short sem_num;/* semaphore number */ 信號量集第幾個信號量的下標
        short  sem_op;   /* semaphore operation */ -1 1 pv操作的值
        short  sem_flg;  /* operation flags */  0
}
int semop(int semid,//id
          struct sembuf sops[] , //數組
          unsigned nsops); //數組元素個數

代碼實現爲:

//循環打印o,x
1 #include <string.h>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <sys/sem.h>
  5 #include <sys/ipc.h>
  6 #include <unistd.h>
  7 
  8 //printox
  9 
 10 int id;
 11 union semun
 12 {
 13     int val;
 14 };
 15 
 16 
 17 void p()
 18 {
 19 
 20     struct sembuf sb[1];//創建結構體數組
 21     sb[0].sem_num=0;//信號量集中第幾個信號量的下標
 22     sb[0].sem_op=-1;//p操作
 23     sb[0].sem_flg=0;
 24     semop(id,sb,1);//進行pv操作
 25 }
 26 void v()
 27 {
 28 
 29     struct sembuf sb[1];//創建結構體數組
 30     sb[0].sem_num=0;//信號量集中第幾個信號量的下標
 31     sb[0].sem_op=1;//v操作
 32     sb[0].sem_flg=0;
 33     semop(id,sb,1);//進行pv操作
 34 }
 35 void printox(char c)
 36 {
 37     int i;
 38 
 39     for(i=0;i<10;i++)
 40     {
 41         p();//保證打印ox交叉執行
 42         printf("%c",c);
 43         fflush(stdout);
 44         sleep(rand()%3);
 45 
 46         printf("%c",c);
 47         fflush(stdout);
 48         sleep(rand()%2);
 49         v();
 50     }
 51 
 52 }
 53 
 54 
 55 int main(void)
 56 {
 57     srand(getpid());//隨機
 58     int id=semget(1235,1,IPC_CREAT|0644);//創建信號量集
 59 
 60     union semun su={1};
 61     semctl(id,0,SETVAL,su);
 62 
 63     //創建子進程
 64     pid_t pid=fork();
 65     if(pid==0)
 66     {
 67         printox('O');
 68     }

運行結果爲:
這裏寫圖片描述

信號量實現哲學家就餐模型(有驚喜哦)


1 #include <iostream>
  2 using namespace std;
  3 #include <stdio.h>
  4 #include <sys/ipc.h>
  5 #include <sys/sem.h>
  6 #include <stdlib.h>
  7 #include <unistd.h>
  8 #include <string.h>
  9 
 10 int id;
 11 union semun
 12 {
 13     int val;
 14 };
 15 
 16 //p
 17 void take2fork(int num)
 18 {
 19     struct sembuf sb[2]={{num,-1,0},{(num+1)%5,-1,0}};
 20     semop(id,sb,2);
 21 }
 22 
 23 void put2fork(int num)
 24 {
 25     struct sembuf sb[2]={{num,1,0},{(num+1)%5,1,0}};
 26     semop(id,sb,2);
 27 }
 28 
 29 void zxj(int num)
 30 {
  31     while(1)
 32     {
 33         printf("%d思考 \n",num);
 34         sleep(rand()%3);
 35         printf("%d我餓了\n",num);
 36         take2fork(num);
 37         printf("%d開吃\n",num);
 38         sleep(rand()%3);
 39         printf("%d好飽\n",num);
 40         put2fork(num);
 41     }
 42 
 43 }
 44 
 45 int main()
 46 {
 47     srand(getpid());
 48     id=semget(1235,5,IPC_CREAT|0644);
 49 
 50     if(id==-1)
 51         perror("semget"),exit(1);
 52 
 53     union semun su={1};
 54 
 55     for(int i=0;i<5;i++)
 56     {
 57         //設置初值
 58         semctl(id,i,SETVAL,su);
 59     }
 60 
 61     int num=0;
 62     for(int i=1;i<5;i++)
 63     {
 64         pid_t pid=fork();
 65         if(pid==0)
 66         {
 67             num=i;
 68             break;
 69         }
 70     }
 71 
 72     zxj(num);
 73 }

模型圖爲:
這裏寫圖片描述

運行結果如下:
這裏寫圖片描述
避免了死鎖的產生!

發佈了128 篇原創文章 · 獲贊 51 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章