System V 信号量机制

      有三种 IPC我们称作XSI IPC,即消息队列、信号量以及共享存储器(共享内存),这就是我么所说的进程间通信的IPC,有了这些IPC提供给程序的通信接口,实现进程间的通信

    本文主要讨论的是信号量的机制

  1. semget()创建一个新的信号量集,或者存取一个已经存在的信号量集:
    系统调用:semget();
    原型:int semget(key_t key,int nsems,int semflg);
    返回值:如果成功,则返回信号量集的IPC标识符。如果失败,则返回-1:errno=EACCESS(没有权限)
    EEXIST(信号量集已经存在,无法创建)
    EIDRM(信号量集已经删除)
    ENOENT(信号量集不存在,同时没有使用IPC_CREAT)
    ENOMEM(没有足够的内存创建新的信号量集)
    ENOSPC(超出限制)
          系统调用semget()的第一个参数是关键字值(一般是由系统调用ftok()返回的)。系统内核将此值和系统中存在的其他的信号量集的关键字值进行比 较。打开和存取操作与参数semflg中的内容相关。IPC_CREAT如果信号量集在系统内核中不存在,则创建信号量集。IPC_EXCL当和 IPC_CREAT一同使用时,如果信号量集已经存在,则调用失败。如果单独使用IPC_CREAT,则semget()要么返回新创建的信号量集的标识 符,要么返回系统中已经存在的同样的关键字值的信号量的标识符。如果IPC_EXCL和IPC_CREAT一同使用,则要么返回新创建的信号量集的标识 符,要么返回-1。IPC_EXCL单独使用没有意义。参数nsems指出了一个新的信号量集中应该创建的信号量的个数。


    程序举例:
    <span style="font-family:Microsoft YaHei;font-size:14px;">intopen_semaphore_set(key_t keyval,int numsems)
    {
        intsid;
        if(!numsems)
            return(-1);
        if((sid=semget(mykey,numsems,IPC_CREAT|0660))==-1)
         {
              return(-1);
         }
         return(sid);
    };</span>

  2. semop函数使用semget打开一个信号量集后,对其中一个或多个信号量的操作就使用semop(op--operate)函数来执行。

    原型:int semop(int semid, struct sembuf *opsptr, size_t nops);
    参数:semid:是semget返回的semid号。
        nops:是数组opsptr的个数。
        opsptr是操作结构的数组

    struct sembuf
    {
       short sem_num;   //信号量在semid集合中的序号:0到nsems - 1;
       short sem_op;   //操作
       short sem_flag;   //0, IPC_NOWAIT, SEM_UNDO
    };

    其中,sem_op值如下:
    a、如果sem_op大于0,表示sem_num信号量所代表的资源的释放,semval += sem_op;
    b、如果sem_op小于0,表示sem_num信号量所代表资源的分配,具体是:如果semval 大于等于 sem_op的绝对值,则semval -= sem_op绝对值;否则,阻塞知道条件满足
    c、如果sem_op等于0,表示直到semval 等于0时才返回。


    程序举例:
    <span style="font-family:Microsoft YaHei;font-size:14px;">static int op_sem(int sem_id, int op, int which)//信号量的操作举例
    {
          struct sembuf sem;
          memset(&sem, '\0', sizeof(sem));
          sem.sem_num = which;
          sem.sem_op = okp;
          sem.sem_flg = 0;
          return semop(sem_id, &sem, 1);
    }</span><pre name="code" class="cpp"><span style="font-family:Microsoft YaHei;">int sem_p(int sem_id, int which)//P操作
    {
          int ret = op_sem(sem_id, -1, which);
          if(ret == 0){
               printf("P operator is success!, errno code is : %d\n", errno);
           }else{
               printf("P operator is failed!, errno code is : %d\n", errno);
           }
            return ret;
    }
    int sem_v(int sem_id, int which)//V操作
    {
           int ret = op_sem(sem_id, 1, which);
           if(ret == 0){
                 printf("V operator is success!, errno code is : %d\n", errno);
             }else{
                printf("V operator is failed!, errno code is : %d\n", errno);
            }
            return ret;
     }</span>

     

  3. semctl函数用来直接控制信号量信息。
    原型:int semctl(int semid, int semnum, int cmd, ../* union semun arg */);
    其中semid是信号量集合,semnum是信号在集合中的序号,

    union semun
    {
        int val; /* cmd == SETVAL */
        struct semid_ds *buf /* cmd == IPC_SET或者 cmd == IPC_STAT */
        ushort *array; /* cmd == SETALL, 或 cmd = GETALL */
    };

    cmd取值如下:

    GETVAL, SETVAL : semid集合中semnum信号量当前的semval值
    GETALL,SETALL :semid集合中所有信号量的值。
    IPC_RMID:删除semid信号量集
    GETPID:返回最后成功操作该信号的进程号。
    IPC_STAT:返回semid集合中的struct semid_ds结构。


  4. 程序举例:
    <span style="font-family:Microsoft YaHei;font-size:14px;">int destroy_sem(int sem_id)//使用semctl删除信号量
    {
    int ret = semctl(sem_id, 0, IPC_RMID, NULL);
    if(ret == -1){
    printf("destroy sem error\n");
    return ret;
    }
    printf("destroy sem success, errno code is : %d\n", errno);
    return ret;
    }</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值