与消息队列和共享内存一样,信号量集也有自己的数据结构:
struct semid_ds {
struct ipc_perm sem_perm; /* Ownership and permissions */
time_t sem_otime; /* Last semop time */
time_t sem_ctime; /* Last change time */
unsigned short sem_nsems; /* No. of semaphores in set */
};
同样地,第一个条目也是共有的ipc 对象内核结 构,剩下的是私有成员。
Each semaphore in a semaphore set has the following associated values:
unsigned short semval; /* semaphore value */
unsigned short semzcnt; /* # waiting for zero */
unsigned short semncnt; /* # waiting for increase */
pid_t sempid; /* process that did last op */
即每一个在信号集中的信号量都有上述4个相关的变量。
1、semval :当前某信号量的资源数目
2、semzcnt:当sem_op(见 struct sembuf)为0,且semop 函数没有设置IPC_NOWAIT 标志,且当前semval 不为0 ,此时进程会阻塞等待直到4个事件发生,具体可man 2 semop 一下,然后semzcnt 会加1,表示等待这个信号量的资源变为 0的进程数加1。
3、semncnt:当sem_op(见 struct sembuf)< 0,且semop 函数没有设置IPC_NOWAIT 标志,且 当前semval < |sem_op| ,此时进程会阻塞等待直到4个事件发生,具体可man 2 semop 一下,然后semncnt 会加1,表 示等待这个信号量的资源增加的进程数加1。
4、当正确执行了semop 函数,则每个信号量的sempid 参数都被设置为 改变此信号量的进程pid。
以下是几个信号量集操作函数:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
int semctl (int semid, int semnum, int cmd, ...);
int semop(int semid, struct sembuf *sops, unsigned nsops);
功 能:用来创建和访问一个信号量集
原型int semget(key_t key, int nsems, int semflg);
参数
key: 信号集的名 字
nsems:信号集中信号量的个数
semflg: 由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样 的
返回值:成功返回一个非负整数,即该信号集的标识码;失败返回-1
功能:用于控制信号量集
原型int semctl(int semid, int semnum, int cmd, ...);
参数
semid:由semget返回的信号集标识码
semnum:信号集中信号 量的序号,从0开始编号
cmd:将要采取的动作(有三个可取值)
最后一个参数是 union semun,具体成员根据cmd 的 不同而不同
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO (Linux- specific) */
};
返回值:成功返回0;失败返回-1