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 }

模型图为:
这里写图片描述

运行结果如下:
这里写图片描述
避免了死锁的产生!

猜你喜欢

转载自blog.csdn.net/kai29/article/details/80219740