进程间通信 [2]

5.2 进程间信号量
进程间信号量的分配,使用和解除分配和共享内存段类似。
5.2.1 分配和解除分配
SYNOPSIS
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>

       int semget(key_t key, int nsems, int semflg);
描述:    semget()会返回与参数key 相关的信号量集的标识符.
        如果,key 值为 IPC_PRIVATE,
        或者,和key相关的信号量集不存在,并且在 semflg中指定了IPC_CREAT,
        那么,一个有 nsems个信号量的的新集合将被创建。
       
        如果,semflg指定了 IPC_CREAT和 IPC_EXCL,并且与 key 相关的信号量集已经存在,
        那么,semget() 返回 EEXIST.(这与 在 open()中指定了 O_CREAT | O_EXCL 类似。)
       
        semflg的低9位决定了owner,group,others对该信号量集的权限。信号量集的可执行权限是没有意义的。

SYNOPSIS
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>

       int semctl(int semid, int semnum, int cmd, ...);
    解除信号量的分配,使用 semctl, semid 为要解除的信号量集的标识符,semnum信号量集中信号量的个数,IPC_RMID 指定了消除操作,第四个参数为
    任何union semun类型的值(这个值是被忽略的,其内容无关紧要)。
    再此处对semctl先不做其他解释。
下面先看一信号量的分配和消除分配的例子,
Listing 5.2 (sem_all_deall.c) Allocating and Deallocating a Binary Semaphore
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
/* We must define union semun ourselves.     */
union semun {
   int val;
   struct semid_ds *buf;
   unsigned short int *array;
   struct seminfo *__buf;
};
/* Obtain a binary semaphore’s ID, allocating if necessary.    */
int binary_semaphore_allocation (key_t key, int sem_flags)
{
   return semget (key, 1, sem_flags);
}
/* Deallocate a binary semaphore. All users must have finished their
    use. Returns -1 on failure. */
int binary_semaphore_deallocate (int semid)
{
   union semun ignored_argument;
   return semctl (semid, 1, IPC_RMID, ignored_argument);
}

5.2.2 进程间信号量的初始化
信号量的分配和初始化是两个相互独立的操作。为了初始化一个信号量,还要使用 semctl,第一参数为 线号量集的标识符,0 作为第二个参数,SETALL作为第三个参数。对于第四个参数,你必须创建一个union semun 类型的对象,并且让的array域指向一个 unsigned short 类型的数组。这个数组中的每个值都是用来初始化信号量集中的一个信号量的。
下面是个初始化一个二值信号量的例子,
Listing 5.3 (sem_init.c) Initializing a Binary Semaphore
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/* We must define union semun ourselves.   */
union semun {
   int val;
   struct semid_ds *buf;
   unsigned short int *array;
   struct seminfo *__buf;
};
/* Initialize a binary semaphore with a value of 1. */
int binary_semaphore_initialize (int semid)
{
   union semun argument;
   unsigned short values[1];
   values[0] = 1;
   argument.array = values;
   return semctl (semid, 0, SETALL, argument);
}

5.2.3 wait 和 Post 操作
每个信号量都有一个非负的值,支持wait和post操作。系统调用 semop 可以完成这两种操作。第一个参数为一个信号量集的标识符。第二个参数为一个
struct sembuf 类型的数组,它指定了你想要完成的操作。第三个参数为第二个参数数组的长度。
struct sembuf 的每个域如下,
@  sem_num,是信号量集中的信号量的个数。
@    sem_op,是个整数,制定了信号量的操作。
        如果, sem_op 是个正值,那么这个值立即加在信号的值上。
        如果, sem_op 是个非正值,那么从信号量的值中减去这个数的绝对值。如果这样做使得信号量的值为负,那么这次调用将阻塞,直到信号量的值
        变到大于 sem_op的绝对值。(因为其他进程可能会使信号量的值增加。)
@    sem_flg 是个flag值。如果它指定为 IPC_NOWAIT,那么它将使得 semop操作非阻塞。如果一个进程由于调用了semop应当被阻塞,但是因为指定了
    IPC_NOWAIT那么semop将调用失败而返回,却不会阻塞进程。如果指定了SEM_UNDO,Linux自动取消一个退出进程对信号量的操作。

如下为一个二值信号量的 w 和 p 操作示例,
Listing 5.4 (sem_pv.c) Wait and Post Operations for a Binary Semaphore
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/* Wait on a binary semaphore.   Block until the semaphore value is positive, then
    decrement it by 1. */
int binary_semaphore_wait (int semid)
{
  struct sembuf operations[1];
  /* Use the first (and only) semaphore.   */
  operations[0].sem_num = 0;
  /* Decrement by 1. */
  operations[0].sem_op = -1;
  /* Permit undo’ing. */
  operations[0].sem_flg = SEM_UNDO;
  return semop (semid, operations, 1);
}
/* Post to a binary semaphore: increment its value by 1.
    This returns immediately. */
int binary_semaphore_post (int semid)
{
  struct sembuf operations[1];
  /* Use the first (and only) semaphore.   */
  operations[0].sem_num = 0;
  /* Increment by 1. */
  operations[0].sem_op = 1;
  /* Permit undo’ing. */
  operations[0].sem_flg = SEM_UNDO;
  return semop (semid, operations, 1);
}

补充:
每一个信号量中都有如下相关的值:
@    unsigned short semval;//信号量的值
@    unsigned short semzcnt;//# waiting for zero
@    unsigned short semncnt;//# waiting for increase
@    pid_t                sempid;//最后一个操作信号量的进程的进程ID
...

5.2.4 信号量调试
使用 ipcs -s显示当前系统中存在的信号量集
使用 ipcrm sem semaphore_set_identifier 删除一个存在的信号量集

下面是个完整的例子,例子中,进程A向共享内存写入数据,执行 V 操作,再执行 P 操作,从共享内存读出数据,退出。进程B 中 执行 P 操作,然后从
共享内存中读出数据,再向其中写入数据。然后退出。注意:本程序应先运行A,马上在运行B.示意性的。

 

你还可以参考:http://blog.csdn.net/liranke/archive/2010/05/15/5595734.aspx

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值