System V信号量是不属于POSIX标准,它属于SUS(Single UNIX Specification)单一UNIX规范中的扩展定义。它和POSIX信号量一样都提供基本的信号量功能操作。
System V信号量相对于POSIX信号量最大的区别是在信号量的操作复杂度。
在POSIX信号量中说过,根据信号量取值(代表可用资源的数目)的不同,POSIX信号量可以分为:
- 二值信号量:信号量的值只有0和1,这和互斥量很类型,若资源被锁住,信号量的值为0,若资源可用,则信号量的值为1;
- 计数信号量:信号量的值在0到一个大于1的限制值(POSIX指出系统的最大限制值至少要为32767)。该计数表示可用的资源的个数。
相对于POSIX信号量,System V信号量增加了复杂度,我们称System V信号量之为:计数信号量集。计数信号量集:至少有一个信号量构成的集合,其中集合中的每个信号量都是计数信号量。对于信号量集中的信号量数目系统内核是存在限制的,由内核参数:SEMMSL决定。
[root@localhost ~]# grep SEMMSL -R /usr/include/*
/usr/include/linux/sem.h:#define SEMMSL 250 /* <= 8 000 max num of semaphores per id */
... ...
对于System V信号量,系统内核还有很多限制,譬如下面:
SEMMNS:系统中信号量的最大数目,等于SEMMNI*SEMMSL
SEMOPM:一次semopt()操作的最大信号量数目
SEMMNI。系统内核中信号量的最大数目
对于系统中的每个
System V
信号量,即每个信号量集,内核都会维护一个
semid_ds
的信息结构,如下是Linux 2.6.18下的定义 :
/* Data structure describing a set of semaphores. */
struct semid_ds
{
struct ipc_perm sem_perm; // IPC的操作权限,每个IPC结构都有
__time_t sem_otime; //上一次执行semop() 的时间
unsigned long int __unused1; //预留使用
__time_t sem_ctime; //上一次通过semctl()进行的修改时间
unsigned long int __unused2;
unsigned long int sem_nsems; //信号量集中的信号量数目
unsigned long int __unused3;
unsigned long int __unused4;
};
在《APUE》P423提到,信号量集中每一个信号量由一个无名结构表示。但是我始终无法找到该结构体的定义,书中提到该结构的定义如下:
struct {
unsigned short semval; //信号量的值
pid_t sempid; //最后一次semctl操作的进程id
unsigned short semncnt; //等待semval变为大于当前值的线程数
unsigned short semzcnt; //等待semval变为0的线程数
};
1 System V信号量的创建和打开
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
//若成功就返回飞非负的标识符,否则返回-1
semget用于创建或打开一个已存在的信号量。
key:用于生成唯一信号量的key,主要的目的是使不同进程在同一该IPC汇合。key可以是事先不同的进程约定好的一个值,也可以不同进程通过相同的路径名和项目ID,调用ftok()函数,生成一个键。
nsems:表示信号量集中信号量的个数,如果创建一个信号量集,nsems必须是一个非