1.概述
SystemV信号量并不如Posix信号量那样“好用”,但相比之下它的年代更加久远,但是SystemV使用的却更加广泛(尤其是在老系统中)。在学习Posix信号量的时候,已经大概清楚了二值信号量
和计数信号量
是什么东西。在接触SystemV信号量之后,这里有一个新的概念叫做:计数信号量集。其实就是把信号量放入数组中,不过都用一些特别的结构封装。
2. systemV信号量编程
函数接口就比较少了,书上介绍了三个:semget
,semctl
、semop
。
2.1 semget函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
第一个参数key通过ftok根据特定path获取
第二个参数表示信号量集中信号量数(可以理解为数组的大小)
第三个参数标志位比如:senflg=O_CREAT|O_EXCL|0644
systemV信号随内核持续的,semget
调用成功后,在内核会维护一个信息结构(可以理解为信号量集的表头,或者链表的头节点),里面包含了一些信息:
struct semid_ds {
struct ipc_perm sem_perm; //例如0644,0600,也有一些宏特别指定,不过还是数字好记
time_t sem_otime;
time_t sem_ctime;
unsigned long sem_nsems;
struct sem * sem_base;//这一项在man page中没有明确表示
//但man page提到信号量集中有这样的结构
};
struct sem
表示封装的信号量结构
struct sem
{
unsigned short semval; /* semaphore value */
unsigned short semzcnt; /* # waiting for zero */
unsigned short semncnt; /* # waiting for increase */
pid_t sempid; /* ID of process that did last op */
};
根据这两个结构体,在内核中某个特定信号量集可以图解为:
2.2 semop函数
使用semget
打开一个信号量后,可以对其中一个或多个信号量操作使用semop
函数来执行。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
对于struct sembuf
这个结构体来说,其结构定义如下:
struct sembuf{
unsigned