信号量

原创:http://blog.sina.com.cn/u/2312748742

一、信号量时一种变量,只能取正整数值,对于这个信号量只能进行如下两种操作:
1)P-代表等待,它是刚要进入关键代码时的操作,如果Sem_info大于0就对Sem_info进行减1处理,
如果Sem_info=0则进行挂起等待。
2)V-代表信号。它是刚要离开关键代码时的操作,如果有其他进程在等待着而被挂起了,就让他
恢复执行,如果没有进程因等待而被挂起就对Sem_info进行加1处理,

最简单的信号量可以只取0和1,也就是常说的二进制信号量,也可称互斥信号量。
也可以取多种正整数值得信号量,也可称:通用信号量。

二、创建信号量或者取得一个现有的信号量

int semget(key_t key,int num_sems,in sem_flag);

   1)key:一个整数值,不相关的进程将通过它取访问同一个信号量。

   2)num_sems: 需要使用的信号量个数,创建信号量集时小于SEMMSL.

   3)sem_flgs: 一组标志。

三、改变信号量的键值

int semop(int sem_id,struct sembuf *sem_ops, size_t num_sem_ops)

   1)sem_id:信号量的标识码,是semget返回的值

   2)sem_ops:指向一个结构体指针。

   3)semop 调用信号量一次完成,避免使用多个信号量发生竞争,看创建几个信号量。

四、控制信号量的信息

 int semctl(int sem_id,int sem_num,int command,...);

   1)sem_id,返回的标号

   2)sem_num 信号量的编号,可以使用成组的信号,0表示唯一一个。

   3)comman:采取的动作。SETVAL:用来把信号量初始化一个已经知道的值,在semun结构里的 IPC_RMID删除一个已经知道的值。

   4)....:一个union semun复合结构

 

 五、

  struct sembuf

   {

     short sem_num;

     short sem_op;

     short sem_flg;

   };

   1)sem_num:信号量的编号,0表示唯一一个编号。

   2)sem_op信号量的pv操作时加减的数值。一般就两个值,-1表示P操作,等待信号量变得可用,+1进行V操作,发出的信号变得可用。

   3)sem_flg:通常设置为SEM_UNDO,由操作系统跟踪,若进程异常退出则内核自动释放p操作,避免死锁。

 

注:ipcrm 可以删除信号量等,man ipcrm查看

 

例子:

进行v操作,生产馒头:

#include<sys/msg.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include <unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<signal.h>
#include<string.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#define ERR_INFO(info)\
do\
\
 perror(info);\
 exit(EXIT_FAILURE);\
}while(0);  //与分好结束


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

int main()
{
  int semID=semget((key_t)1000,1,IPC_CREAT|0777);
  if(semID==-1)
  {
    ERR_INFO("semget error\n");  
  }
  union semun initValue;
  initValue.val=0; //还未产生 (可以设置信号集初始化个数)若果设置5,则刚开始就有5个馒头
  //初始化
  int semc=semctl(semID,0,SETVAL,initValue.val);
  if(semc==-1)
  {
   ERR_INFO("semctla error\n"); 
  }
  struct sembuf sem_v;  //库里定义的  改变信号
  while(1)
  
   char ch=getchar();
   if(ch=='q')
   break;
   sem_v.sem_num=0;  //下标
   sem_v.sem_op=1; //进行V操作, 如果设置为6则说明一次v操作将产生6个馒头
   sem_v.sem_flg=SEM_UNDO;
   semop(semID,&sem_v,1);  //生产
   printf("creat 1 task\n");
  }
  semctl(semID,0,IPC_RMID,NULL); //删除
}

进行p操作,消费馒头:

#include<sys/msg.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include <unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<signal.h>
#include<string.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#define ERR_INFO(info)\
do\
\
 perror(info);\
 exit(EXIT_FAILURE);\
}while(0);  //与分好结束


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

int main()
{
  int semID=semget((key_t)1000,1,IPC_CREAT|0777); //创建信号量
  if(semID==-1)
  {
    ERR_INFO("semget error\n");  
  }
  
  struct sembuf sem_p;  //信号
  while(1)
  {
   char ch=getchar();
   if(ch=='q')
   break;
   sem_p.sem_num=0;
   sem_p.sem_op=-1;//进行p操作, 如果设置为6则说明一次p操作将消费6个馒头
   sem_p.sem_flg=SEM_UNDO;
   semop(semID,&sem_p,1);   //阻塞时 会阻塞在此
   printf("UNDO 1 task\n");
  }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值