System V 信号量
在提到时,指的是二值信号量或计数信号量,而System V信号量指的是入了计数信号量集
二值信号量:其值为0或1,类似于互斥锁,资源被锁住时为0,资源可用为1
计数信号量:其值在0和某个限制值之间的信号量,信号量的值就是可用资源数计数信号量集:一个或多个信号量构成一个集合,集合中每个元素都是计数信号量(每个集合的信号量数存在一个限制)semid_ds结构:
内核为每个信号量集维护的信息结构
#includestruct semid_ds{ struct ipc_perm sem_perm; // 当前信号量的访问权限 struct sem *sem_base; // 内核用于维护某个给定信号量的一组值的内部数据结构 ushort sem_nsems; // 集合中信号量的数目 time_t sem_otime; // 最近一次执行semop()的时间 time_t sem_ctime; // 集合创建时间或最近一次IPC_SET的时间};struct sem{ ushort_t semval; // 信号量实际值 short sempid; // 对信号量值执行最后一次操作的进程的进程ID ushort_t semncnt; // 等待信号量值增长的进程数 ushort_t semzcnt; // 等待信号量值变为0的进程数};
semget()函数:
#include// 创建一个信号量集或访问一个已存在的信号量集// 成功返回非负信号量标识符,出错返回-1int semget(key_t key, int nsems, int oflag);// key: IPC 键// nsems:指定集合中信号量数// oflag:SEM_R(读)和SEM_A(改)的组合,还可以按位与IPC_CREAT或IPC_CREAT|IPC_EXCL
semop()函数:
#include// 对信号量集中一个或多个信号量进行操作// 成功返回0,出错返回-1int semop(int semid, struct sembuf *opsptr, size_t nops);// semid:由semget()函数返回的信号量标识符// nops: 指出opsptr指向的结构数组的元素数量// opsptr:指向一个如下的数组struct sembuf{ short sem_num; // 信号量集中信号量的索引值:0, 1, ... , nsems-1(sem_base[sem_num], 指定对某个特定信号量进行操作) short sem_op; // 指定对特定信号量的操作 short sem_flg; // 操作标志,0, IPC_NOWAIT、SEM_UNDO};// sembuf结构内元素的排列顺序并不保证如上述那样,只保证该结构中有上述三个元素// sembuf结构不能静态初始化(struct sembuf value = {0, 0, 0} // Error)// sembuf结构需要运行时初始化(struct sembuf value; value.sem_num = 0; ...)// sem_op:每个特定的操作有sem_op确定,它可以是负数、0、正数// sem_op为正数时,其值加到semval(信号量当前值)上,对应于释放信号量控制的资源// 如果指定了SEM_UNDO标志,就从相应信号量的semadj(所指定信号量针对调用进程的调整值)减去sem_op// sem_op为0,调用者等待semval变为0,如果semval已经为0,则立即返回// sem_op为负数,调用者希望等待semval变为大于或等于sem_op的绝对值,这对应于分配资源
semctl()函数:
#include// 对一个信号量执行各种控制操作// 成功返回非负值,出错返回-1int semctl(int semid, int semnum, int cmd, ... /* union semun arg */);// semid: 标识其操作待控制的信号量集// semnum: 标识信号量集内的某个成员(sem_base[sem_num])// cmd:可选值如下(除非另外说明,操作成功函数返回值为0,出错为-1)// GETVAL:将semval的当前值作为函数返回值返回// SETVAL:将semval设为arg.val(若操作成功,那么相应信号量的semadj被设为0)// GETPID:将sempid的当前值作为函数返回值返回// GETNCNT:将semncnt(等待semval变为大于其当前值的线程数)的当前值作为函数返回值返回// GETZCNT:将semzcnt(等待semval变为0的线程数)的当前值作为函数返回值返回// GETALL:返回指定信号量集内每个成员的semval值(这些值通过arg.array指针返回)// SETALL:设置指定信号量集内每个成员的semval值(这些值通过arg.array指针传递)// IPC_RMID:将由semid指定的信号量集从系统删除// IPC_SET:设置指定信号量集的semid_ds结构中的sem_perm.uid、sem_perm.gid、sem_perm.mode,这些值由arg.buf参数指向的结构中的相应成员指定// IPC_STAT:返回指定信号量集当前的semid_ds结构(通过arg.buf)// arg: 可选参数,根据 cmd 参数而定union semun{ int val; struct semid_ds *buf; ushort *array;};