linux网络编程 | 进程间通信-------信号量机制

版权声明:转用请注明出处 https://blog.csdn.net/weixin_39411321/article/details/89405628

1. 进程间的通信方式

进程间的通信有以下几种方式:

1. 管道:管道分为有名管道和无名管道
2. 信号量:通过控制多个进程对临界资源的访问,使得同一时刻只允许一个进程对临界资源进行访问
3. 共享内存:把一块内存空间映射到两个进程的地址空间中,使得他们能够访问同一块内存空间,达到数据的共享。
4. 消息队列:向消息队列中添加数据,从消息队列中读取数据

2. 信号量机制进行进程同步

什么是信号量?信号量(semaphore)的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程。信号量的值与相应资源的使用情况有关。
当它的值大于0时,表示当前可用资源的数量;
当它的值小于0时,其绝对值表示等待使用该资源的进程个数。
注意,信号量的值仅能由PV操作来改变。

同步:对临界资源的互斥访问
临界区:访问临界资源的代码段
临界资源:同一时刻只能有一个进程来访问的资源

3. 原子操作P/V

P : 申请一个资源 资源数目减一,获取资源,进程进入,可能会发生阻塞.
V : 释放一个资源,资源数目加一,释放资源,进程出来,不会发生阻塞

使用PV操作实现进程互斥时应该注意的是:
(1)每个程序中用户实现互斥的P、V操作必须成对出现,先做P操作,进临界区,后做V操作,出临界区。若有多个分支,要认真检查其成对性。
(2)P、V操作应分别紧靠临界区的头尾部,临界区的代码应尽可能短,不能有死循环。
(3)互斥信号量的初值一般为1。

不加同步信号量的程序:

程序A.c

 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<assert.h>
  6 int main()
  7 {
  8     int i=0;
  9     for(;i<5;i++)
 10     {
 11         write(1,"A",1);
 12         int n=rand()%3;
 13         sleep(n);
 14         write(1,"A",1);
 15         n=rand()%3;
 16         sleep(n);
 17     }
 18     sleep(10);
 19     exit(0);
 20 }
 21 

程序B.c

 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<assert.h>
  6 
  7 int main()
  8 {
  9     int i=0;
 10     for(;i<5;i++)
 11     {
 12         write(1,"B",1);
 13         int n=rand()%3;
 14         sleep(n);
 15         write(1,"B",1);
 16         n=rand()%3;
 17         sleep(n);
 18     }
 19     exit(0);
 20 }

运行结果如下
在这里插入图片描述从图中可以看出没有使用信号量机制的时候进程不是同步的;
同步时的输出结果应该是A和B是成对出现的
例如:AABBAABBAAAABBBBAABB这种样子

使用信号量机制后的程序:

程序A.c


  1 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<assert.h>
  6 #include"sem.h"
  7 int main()
  8 {
  9     sem_init();
 10     int i=0;
 11     for(;i<5;i++)
 12     {
 13         sem_p();
 14         write(1,"A",1);
 15         int n=rand()%3;
 16         sleep(n);
 17         write(1,"A",1);
 18         sem_v();
 19         n=rand()%3;
 20         sleep(n);
 21     }
 22     sleep(10);
 23     sem_destroy();
 24     exit(0);
 25 }

程序B.c


  1 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<assert.h>
  6 
  7 int main()
  8 {
  9     sem_init();
 10     int i=0;
 11     for(;i<5;i++)
 12     {
 13         sem_p();
 14         write(1,"B",1);
 15         int n=rand()%3;
 16         sleep(n);
 17         write(1,"B",1);
 18         sem_v();
 19         n=rand()%3;
 20         sleep(n);
 21     }
 22     exit(0);
 23 }
 24 

程序sem.h 为使用信号量同步进程的头文件

 1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<assert.h>
  6 #include<sys/sem.h>
  7 
  8 union semun
  9 {
 10     int val;
 11 };
 12 
 13 void sem_init();
 14 void sem_p();
 15 void sem_v();
 16 void sem_destroy();
~                            

程序sem.c

#include"sem.h"
  2 
  3 
  4 static int semid=-1;
  5 void sem_init()
  6 {
  7     semid=semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);
  8     if(semid==-1)
  9     {
 10         semid=semget((key_t)1234,1,0600);
 11         if(semid==-1)
 12         {
 13             perror("semget error");
 14             return;
 15         }
 16     }
 17     else
 18     {
 19         union semun a;
 20         a.val=1;
 21         if(semctl(semid,0,SETVAL,a)==-1)
 22         {
 23             perror("semctl error");
 24         }
 25     }
 26     return ;
 27 }
 28 
 29 void sem_p()
 30 {
 31 
 32     struct sembuf buf;
 33     buf.sem_num=0;
 34     buf.sem_op=-1;//p
 35     buf.sem_flg=SEM_UNDO;//程序崩掉也会将资源还回去
 36 
 37     if(semop(semid,&buf,1)==-1)
 38     {
 39         perror("semop p error");
 40     }
 41 
 42 }
 43 void sem_v()
 44 {
 45     struct sembuf buf;
 46     buf.sem_num=0;
 47     buf.sem_op=1;//v
 48     buf.sem_flg=SEM_UNDO;//程序崩掉也会将资源还回去
 49 
 50     if(semop(semid,&buf,1)==-1)
 51     {
 52         perror("semop v error");
 53     }
 54 }
 55 void sem_destroy()
 56 {
 57     if(semctl(semid,0,IPC_RMID)==-1)//若删除失败
 58     {
 59         perror("semctl error");
 60     }
 61 
 62 
 63 }

运行结果如下
在这里插入图片描述由运行结果可以看出:使用信号量机制实现了进程之间的同步

猜你喜欢

转载自blog.csdn.net/weixin_39411321/article/details/89405628