进程间通信---信号量

(1)信号量的基本概念:

信号量的本质是一种数据操作锁,它的本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号在此过程中负责数据操作的互斥,同步等功能。

当请求一个信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用。如果大于0,表示资源可以用,等于0表示没有可用资源,这个时候进程会进入睡眠状态直至有资源可用。

当进程不再使用一个信号量来控制共享资源时,信号量的值加1,对信号量的值进行的增减操作均属于原子操作,这个因为信号量主要的作用是维护资源的互斥或多进程的同步访问。

注意:1,一个信号量的生命周期是随内核的。2,信号量必须能够被其他的进程看到。3,查看信号量的命令:ipcs  -s。

(2)信号量的使用:

由于信号量只能进行两种操作,分别是等待信号和发送信号,即P(sv)和V(sv)。

P(sv):如果sv的值大于0,就减一,如果它等于零表示该进程挂起(进程的挂起本身就是PCB的挂起)

V(sv):如果其他进程因为等待sv而被挂起,就让他恢复运行,如果没有进程因等待sv而被挂起,就给他加一。

(3)创建信号量:


key:唯一非零的整数,其他的进程可以通过key值来访问这个信号量,它代表程序可能使用的某个资源,程序对所有信号量的访问都是间接的。程序先通过调用segment函数并提供一个建,再由系统生成一个相应的信号标识符。只有segment函数才直接调用信号量键。

nsems:指定需要的信号量数目。

semflg:IPC_CREAT   IPC_EXCL,如果只是单独使用IPC_CREAT则表示,如果这个有这个信号量,那么便使用这个信号量,如果这个信号量没有那么就创建一个。如果两个都是用,那么表示,如果这个信号量没有,则创建一个,如果有就会报错。

(4)改变信号量的值:


semid:semget函数返回的信号量标识符。

unsigned short sem_num:一般为0,除非有其他的信号量
           short          sem_op:由P操作和V操作返回的值,分别为+1,-1
           short          sem_flg:一般是SEM_UNDO
SEM_UNDO用于将修改的信号量值在进程正常退出或异常退出时归还给信号量

nsops:设置的信号量值

(5)控制信号量:


semid:semget函数返回的信号量标识符

sennum:设置信号量的值

cmd:它有四种值:IPC_STAT,IPC_SET,IPC_RMID,IPC_INFO

如果有第四个参数,那就是:

union semun {
               int              val;   
               struct semid_ds *buf;    
               unsigned short  *array; 
               struct seminfo  *__buf;  
           };

(6)现在我们使用上面的函数来用信号量实现进程之间的通信:

 1 #ifndef _COMM_H_
  2 #define _COMM_H_
  3 #include<stdio.h>
  4 #include<sys/types.h>
  5 #include<sys/ipc.h>
  6 #include<sys/sem.h>
  7 #include<string.h>
  8 #include<stdlib.h>
  9 #define PATHNAME "."
 10 #define PROJ_ID 6666
 11 
 12 union SemNo
 13 {
 14         int val;
 15         struct semid_ds* buf;
 16         unsigned short* array;
 17         struct seminfo* _buf;
 18 };
 19 
 20 int CreateSemset(int nums);
 21 int GetSemGet();
 22 int InitSemSet(int semid,int num);
 23 int P(int semid);
 24 int V(int semid);
 25 int DestorySet(int semid);
 26 #endif

1 #include"comm.h"
  2 
  3 int CommSemSet(int flags,int nums)
  4 {
  5         key_t _key=ftok(PATHNAME,PROJ_ID);
  6         if(_key<0)
  7         {
  8                 perror("ftok");
  9                 sleep(3);
 10                 return -1;
 11         }
 12         int semid=semget(_key,nums,flags);
 13         if(semid<0)
 14         {
 15                 perror("semget");
 16                 sleep(3);
 17                 return -2;
 18         }
 19         return semid;
 20 }
 21 int CreateSemSet(int nums)
 22 {
 23         return CommSemSet(IPC_CREAT|IPC_EXCL|0666,nums);
 24 }
 25 int GetSemSet()
 26 {
 27         return CommSemSet(0,0);
 28 }
 29 int InitSemSet(int semid,int nums)
 30 {
 31         union SemNo _sn;
 32         _sn.val=1;
 33         if(semctl(semid,nums,SETVAL,_sn)<0)
 34         {
 35                 perror("semctl");
 36                 sleep(3);
 37                 return -1;
 38         }
 39         return 0;
 40 }
 41 int CommPV(int semid,int nums,int flags)
 42 {
 43         struct sembuf _s[1];
 44         _s[0].sem_op=flags;
 45         _s[0].sem_num=nums;
 46         if(semop(semid,_s,1)<0)
 47         {
 48                 perror("semop");
 49                 sleep(3);
 50                 return -1;
 51         }
 52         return 0;
 53 }
 54 int P(int semid)
 55 {
 56         return CommPV(semid,0,-1);
 57 }
 58 int V(int semid)
 59 {
 60         return CommPV(semid,0,1);
 61 }
 62 int DestorySemSet(int semid)
63 {
 64         if(semctl(semid,0,IPC_RMID)<0)
 65         {
 66                 perror("semctl");
 67                 sleep(3);
 68                 return -1;
 69         }
 70         return 0;
 71 
 72 }
 73 
 74 int main()
 75  {
 76          int semid=CreateSemSet(1);
 77          InitSemSet(semid,0);
 78          pid_t id=fork();
 79          if(id==0)
 80          {
 81                  int semdi=GetSemSet();
 82                  while(1)
 83                  {
 84                          P(semid);
 85                          printf("A");
 86                          fflush(stdout);
 87                          usleep(300000);
 88                          printf("a");
 89                          fflush(stdout);
 90                          usleep(300000);
 91                          V(semid);
 92                  }
 93          }
 94  else
 95          {
 96                  while(1)
 97                  {
 98                          P(semid);
 99                          printf("B");
100                          fflush(stdout);
101                          usleep(300000);
102                          printf("b");
103                          fflush(stdout);
104                          usleep(300000);
105                          V(semid);
106                  }
107          }
108  }
109 
其运行结果为:






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值