名字:
semget - 获得一个System V信号量集合识别符
概要:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
描述:
semget()系统调用返回和参数key关联的System V信号量集合标识符。如果key的值是IPC_PRIVATE或者还没有信号量集合和key关联,并且IPC_CREAT标志有在semflg里面,那么一个新的由nsems个信号量组成的集合就被创建了。
如果semflg有IPC_CREAT和IPC_EXCL,并且key已经有了一个关联的信号量集合,那么semget()失败并且将errno设置为EEXIT。(这个和组合O_CREAT | O_EXCL对于open(2)有点类似)。
对于创建,参数semflg的低9位定义了信号量集合的权限(对于所有者、组、其它)。这些位和open(2)的mode参数类似,有相同的形式、相同的意义。(尽管对于信号量来说执行权限没有意义,写权限意味着改变信号量值的权限)。
当创建一个新的信号量集合的时候,semget()初始化了集合相关联的数据结构,semid_ds (见 semctl(2)),如下:
sem_perm.cuid 和 sem_perm.uid被设置成调用进程的有效用户ID。
sem_perm.cgid 和 sem_perm.gid被设置成调用进程的有效组ID。
sem_perm.mode的低9位被设置成semflg的低9位。
sem_nsems被设置成nsems。
sem_otime设置成0。
sem_ctime设置成当前时间。
当信号量集合不是在创建的过程中的时候,nsems可以是0。当在信号量集合正在被创建过程中,nsems必须大于0并且小于等于一个信号量集合允许的最多的信号量数目(SEMMSL)。
如果信号量集合已经存在了,那么权限会被验证。
返回值:
如果成功,返回值是信号量集合标识符(一个非负整数),否则返回-1,errno会表明错误的类型。
错误:
当发生错误的时候,errno会被设置成以下的值:
EACCES: 对于key存在一个信号量集合,但是调用进程没有权限访问这个集合,并且在用户空间没有用于管理IPC namespace的CAP_IPC_OWNER功能。
EEXIST: IPC_CREAT和IPC_EXCL标志有在semflg里面,但是key已经有了关联的信号量集合。
EINVAL: nsems小于0或者大于信号量集合允许的最大信号量数量(SEMMSL)。
EINVAL: key关联的信号量集合已经存在,但是nsems大于集合中的信号量个数。
ENOENT: key没有对应的信号量集合存在,并且semflg没有IPC_CREAT标志。
ENOMEM: 系统没有足够的空间创建信号量集合。
ENOSPC: 已经达到系统约束的信号量集合数量(SEMMNI),或者达到系统允许的信号量数量(SEMMNS),无法创建新的信号量集合。
遵守:
SVr4, POSIX.1-2001
注意:
包含<sys/types.h>和<sys/ipc.h>在Linux或者其它POSIX版本下面都不是必须的。但是有些老的实现需要包含这些头文件,SVID也记录了他们的包含。要兼容这些旧系统的应用可能需要包含这些头文件。
IPC_PRIVATE不是一个标志位而是一个key_t类型的数据。如果这个值用做key,系统调用忽略semflg除了低9位以外的位,然后创建一个新的信号量集合(成功的话)。
信号量初始化
新创建的信号量集合中的信号量的值是不确定的。(POSIX.1-2001和POSIX.1-2008明确了这一点,虽然POSIX.1-2008提到未来的标准可能你需要要求信号量初始化为0)虽然Linux和其它实现一样,将信号量的值初始化为0,一个可移植的应用不应该依靠这一点:它应该明确的初始化信号量为想要的值。
初始化可以通过semctl(2)的SETVAL或者SETALL操作。当多个对象不知道哪个会初始化集合的时候,检查sem_otime这个值可以避免竞争的出现。semctl(2)的IPC_STAT操作可以检索包含sem_otime的数据结构。
信号量约束
以下的信号量集合相关的资源会影响semget()调用:
SEMMNI: 系统级别对于信号量几何数量的限制。在Linux3.19之前的版本,这个默认值是128。从Linux3.19开始,这个值是32000。在Linux上面这个值可以通过/proc/sys/kernel/sem的第四个字段进行读取和修改。
SEMMSL:每个信号量ID允许的最大数量信号量个数。3.19之前的Linux,这个约束的默认值是250.自从Linux3.19之后开始,这个值是32000.在Linux上这个值可以通过/proc/sys/kernel/sem的第一个字段修改或者读取。
SEMMNS: 系统级别的信号量数量约束。实现相关:(在Linux,这个约束可以通过/proc/sys/kernel/sem的第二个字段修改和读取。)注意,系统级别的信号量数目还受到SEMMSL和SEMMNI的乘积的约束。
Bugs
IPC_PRIVATE这个名字起的不好,IPC_NEW更准确一些。
相关
semctl(2), semop(2), ftok(3), capabilities(7), sem_overview(7), svipc(7)
版本记录
4.15