进程间通信(四):信号量

一,基本概念

      XSI的api是对信号量集合的创建和操作,一个信号量集合包含一个或多个信号量,

二.api 

   1. int semget(key_t key, int nsems, int flag)

       根据key获取或者创建一个信号集

       key:IPC关键字, nsems:创建时表示信号量的个数,flag: 可以是IPC_CREAT | IPC_EXCL | 0660

       返回值是信号量的标识符


  2.int semctl(int semid, int semnum, int cmd, .../* union semun arg */)

        设置或者获取此信号量集合的信息

        

 3.int semop(int semid, struct sembuf semoparray[], size_t nops)

       释放或者获取信号量,semid:标识信号, struct sembuf 的结构定义如下:

       struct sembuf
{
  unsigned short int sem_num; /* semaphore number */
  short int sem_op; /* semaphore operation */
  short int sem_flg; /* operation flag */
};

       sem_num表示此信号集中几个信号量,

        sem_op 为正表示释放,为负标识获取,为0表示等到此信号量变成0,

         sem_flg   可以是IPC_NOWAIT,UNDO;  IPC_NOWAIT表示此信号量不阻塞,注意此处,semoparray是一个数组,flag起作用是有顺序的,

        如何根据数组的第一个元素,判断需要等待或者条件不满足返回,第二个元素就不其作用了,如果第一个满足条件,会继续判断第二个元素,...类推

       UNDO表示,进程终止时,会把此次操作导致的信号量变化调整过来,注意信号量的值不能为负,所以当需要调整到负时,会调整为0

        如果一个进程重新设置了此信号量,所有进程中对于此信号量的调整都会设置为0;

三,一个例子

sem_require.c:

#include<stdlib.h>

#include<stdio.h>
#include<sys/sem.h>
#include<sys/ipc.h>
//#include<linux/sem.h>
//#include<linux/ipc.h>
#include<errno.h>
#include<unistd.h>
#define SEMFILEPATH "/tmp/sem4.txt"
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
};
int main()
{
key_t key  = ftok(SEMFILEPATH, 1);
union semun initval;
initval.array = (unsigned short *)malloc(2*sizeof(unsigned short));
int count = 0;
struct sembuf aqrval[2];
int ret;
   int semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0660);
   if(semid < 0 && EEXIST == errno)
    {
  printf("sem exist ! \n");
semid = semget(key, 2, 0);
  if(semid < 0)
  {
  printf("get sem failed !");
    return 0;
  }
    }
   else
   {
  initval.array[0]=3;
  initval.array[1]=3;
  ret = semctl(semid, 0, SETALL, initval);
  if(ret < 0)
  {
  printf("semctl failed !");
  free(initval.array);
  return 0;
  }
   }
   printf("in aquire: semid, %d\n", semid);
   initval.array[0] = 0;
   initval.array[1] = 0;
   if(semctl(semid, 0, GETALL, initval) >= 0)
    {
    printf("in aquire:sem 1 res %d,sem 2 res %d \n", initval.array[0], initval.array[1]);
    }
   else
   {
  printf("errorno: %d \n", errno);
   }


   while(count++ < 1)
   {
  aqrval[0].sem_num = 0;
  aqrval[0].sem_op = -4;
  aqrval[0].sem_flg =  0;
  aqrval[1].sem_num = 1;
  aqrval[1].sem_op = -4;
  aqrval[1].sem_flg = IPC_NOWAIT;
  ret = semop(semid, aqrval, 2);
  if(ret < 0)
   {
    printf("in aquire:sem_op error ! errno:%d\n", errno);
   }


  if(semctl(semid, 0, GETALL, initval) >= 0)
   {
    printf("in aquire:sem 1 res %d,sem 2 res %d \n", initval.array[0], initval.array[1]);
   }
   }


    return 0;
}


sem_release.c:

#include<stdlib.h>
#include<stdio.h>
#include<sys/sem.h>
#include<sys/ipc.h>
//#include<linux/sem.h>
//#include<linux/ipc.h>
#include<errno.h>
#include<unistd.h>
#define SEMFILEPATH "/tmp/sem4.txt"
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
};
int main()
{
key_t key  = ftok(SEMFILEPATH, 1);
union semun initval;
initval.array = (unsigned short *)malloc(2*sizeof(unsigned short));
struct sembuf aqrval[2];
int ret = 0;
int count = 0;
   int semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0660);
   if(semid < 0 && EEXIST == errno)
    {
  printf("sem exist ! \n");
semid = semget(key, 2, 0);
  if(semid < 0)
  {
  printf("get sem failed !");
    return 0;
  }
    }
   else
   {
  initval.array[0]=3;
  initval.array[1]=3;
  ret = semctl(semid, 0, SETALL, initval);
  if(ret < 0)
  {
  printf("semctl failed !");
  free(initval.array);
  return 0;
  }
   }
   printf("sem exist ! out\n");
   printf("semid: %d\n", semid);
   initval.array[0] = 0;
   initval.array[1] = 0;


   while(count < 2)
   {
   aqrval[count].sem_num = 0;
   aqrval[count].sem_op =  3 + count;
   aqrval[count].sem_flg =  0;
   ret = semop(semid, aqrval, 1);
printf("in relase: realease result:%d\n", ret);
   sleep(5);
   count++;
   }
    return 0;
}                                 

  sem_aquire.c 编译成sem_aquired,  sem_release.c编译成  sem_released

  执行结果如下:

[read_ng@wukong workspace]$ ./sem_aquired &
[1] 14774
[read_ng@wukong workspace]$ in aquire: semid, 196614
in aquire:sem 1 res 3,sem 2 res 3 


[read_ng@wukong workspace]$ ./sem_released &
[2] 14776
[read_ng@wukong workspace]$ sem exist ! 
sem exist ! out
semid: 196614
in relase: realease result:0
in aquire:sem_op error ! errno:11
in aquire:sem 1 res 6,sem 2 res 3 
in relase: realease result:0


[1]-  Done                    ./sem_aquired
[2]+  Done                    ./sem_released
[read_ng@wukong workspace]$   



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值