semctl() - Unix、Linux 系统调用
Tutorials Point


  Unix 初学者指南
  Unix Shell 编程
  高级 Unix
  Unix 有用参考
  Unix 有用资源
  精选读物

版权所有 © 2014 tutorialspoint



  首页     参考     讨论论坛     关于 TP  

semctl() - Unix、Linux 系统调用


previous next AddThis Social Bookmark Button

广告

名称

semctl - 信号量控制操作

语法

#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/sem.h> 

int semctl(int semid, int semnum, int cmd, ...);

描述

semctl() 对由 semid 标识的信号量集或该集合中的第 semnum 个信号量执行由 cmd 指定的控制操作。(集合中的信号量从 0 开始编号。)

此函数有三个或四个参数,具体取决于 cmd。当有四个参数时,第四个参数的类型为 union semun调用程序必须按如下方式定义此联合体


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) */
};

semid_ds 数据结构在 <sys/sem.h> 中定义如下


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_perm 结构在 <sys/ipc.h> 中定义如下(突出显示的字段可以使用 IPC_SET 设置)


struct ipc_perm {
    key_t key;            /* Key supplied to semget() */
    uid_t uid;            /* Effective UID of owner */
    gid_t gid;            /* Effective GID of owner */
    uid_t cuid;           /* Effective UID of creator */
    gid_t cgid;           /* Effective GID of creator */
    unsigned short mode;  /* Permissions */
    unsigned short seq;   /* Sequence number */
};

cmd 的有效值为

标签描述
IPC_STAT 将与 semid 关联的内核数据结构中的信息复制到 arg.buf 指向的 semid_ds 结构中。semnum 参数被忽略。调用进程必须对信号量集具有读取权限。
IPC_SET arg.buf 指向的 semid_ds 结构的一些成员的值写入与该信号量集关联的内核数据结构,并更新其 sem_ctime 成员。更新结构的以下成员:sem_perm.uidsem_perm.gid 和(sem_perm.mode 的最低 9 位)。调用进程的有效 UID 必须与信号量集的所有者(sem_perm.uid)或创建者(sem_perm.cuid)匹配,或者调用者必须具有特权。semnum 参数被忽略。
IPC_RMID 立即删除信号量集,唤醒所有在该集合上阻塞在 semop() 调用中的进程(并返回错误,并将 errno 设置为 EIDRM)。调用进程的有效用户 ID 必须与信号量集的创建者或所有者匹配,或者调用者必须具有特权。semnum 参数被忽略。
IPC_INFO(Linux 特定)
 将系统范围内的信号量限制和参数信息返回到 arg.__buf 指向的结构中。如果定义了 _GNU_SOURCE 功能测试宏,则此结构的类型为 seminfo,在 <sys/sem.h> 中定义

struct seminfo { int semmap; /* # of entries in semaphore map; unused */ int semmni; /* Max. # of semaphore sets */ int semmns; /* Max. # of semaphores in all semaphore sets */ int semmnu; /* System-wide max. # of undo structures; unused */ int semmsl; /* Max. # of semaphores in a set */ int semopm; /* Max. # of operations for semop() */ int semume; /* Max. # of undo entries per process; unused */ int semusz; /* size of struct sem_undo */ int semvmx; /* Maximum semaphore value */ int semaem; /* Max. value that can be recorded for semaphore adjustment (SEM_UNDO) */ };

semmslsemmnssemopmsemmni 设置可以通过 /proc/sys/kernel/sem 进行更改;有关详细信息,请参见 proc(5)。
SEM_INFO(Linux 特定)
 返回一个 seminfo 结构,其中包含与 IPC_INFO 相同的信息,但以下字段返回有关信号量消耗的系统资源的信息:semusz 字段返回系统上当前存在的信号量集的数量;semaem 字段返回系统上所有信号量集中信号量的总数。
SEM_STAT(Linux 特定)
 返回一个 semid_ds 结构,如 IPC_STAT 所示。但是,semid 参数不是信号量标识符,而是内核内部数组中的索引,该数组维护有关系统上所有信号量集的信息。
GETALL 将集合中所有信号量的 semval(即当前值)返回到 arg.arraysemnum 参数被忽略。调用进程必须对信号量集具有读取权限。
GETNCNT 系统调用返回集合中第 semnum 个信号量的 semncnt 值(即等待此信号量值增加的进程数)(即等待第 semnum 个信号量的 semval 增加的进程数)。调用进程必须对信号量集具有读取权限。
GETPID 系统调用返回集合中第 semnum 个信号量的 sempid 值(即对第 semnum 个信号量执行最后一次 semop() 调用的进程的 PID)。调用进程必须对信号量集具有读取权限。
GETVAL 系统调用返回集合中第 semnum 个信号量的 semval 值。调用进程必须对信号量集具有读取权限。
GETZCNT 系统调用返回集合中第 semnum 个信号量的 semzcnt 值(即等待此信号量值变为零的进程数)(即等待第 semnum 个信号量的 semval 变为 0 的进程数)。调用进程必须对信号量集具有读取权限。
SETALL 使用 arg.array 设置集合中所有信号量的 semval并更新与该集合关联的 semid_ds 结构的 sem_ctime 成员。所有进程中已更改信号量的撤消条目(请参见 semop(2))将被清除。如果信号量值的更改允许其他进程中阻塞的 semop() 调用继续执行,则唤醒这些进程。semnum 参数被忽略。调用进程必须对信号量集具有更改(写入)权限。
SETVAL 将集合中第 semnum 个信号量的 semval 值设置为 arg.val,并更新与该集合关联的 semid_ds 结构的 sem_ctime 成员。所有进程中已更改信号量的撤消条目将被清除。如果信号量值的更改允许其他进程中阻塞的 semop() 调用继续执行,则唤醒这些进程。调用进程必须对信号量集具有更改权限。

返回值

如果失败,semctl() 将返回 -1,并使用 errno 指示错误。

否则,系统调用将返回一个非负值,具体取决于 cmd,如下所示

标签描述
GETNCNT semncnt 的值。
GETPID sempid 的值。
GETVAL semval 的值。
GETZCNT semzcnt 的值。
IPC_INFO 内核内部数组中最高使用条目的索引,该数组记录有关所有信号量集的信息。(此信息可与重复的 SEM_STAT 操作一起使用,以获取有关系统上所有信号量集的信息。)
SEM_INFO IPC_INFO 相同。
SEM_STAT 信号量集的标识符,其索引在 semid 中给出。
所有其他 cmd 值在成功时返回 0。

错误

如果失败,errno 将设置为以下之一
标签描述
EACCES cmd 参数具有 GETALLGETPIDGETVALGETNCNTGETZCNTIPC_STATSEM_STATSETALLSETVAL 中的一个值,并且调用进程对信号量集没有所需的权限,并且没有 CAP_IPC_OWNER 功能。
EFAULT arg.bufarg.array 指向的地址不可访问。
EIDRM 信号量集已删除。
EINVAL cmdsemid 的值无效。或者:对于 SEM_STAT 操作,semid 中指定的索引值引用了当前未使用的数组槽。
EPERM cmd 参数的值为 IPC_SETIPC_RMID,但调用进程的有效用户 ID 不是信号量集的创建者(在 sem_perm.cuid 中找到)或所有者(在 sem_perm.uid 中找到),并且进程没有 CAP_SYS_ADMIN 功能。
ERANGE cmd 参数的值为 SETALLSETVAL,并且要设置为 semval 的值(对于集合中的某个信号量)小于 0 或大于实现限制 SEMVMX

注释

IPC_INFOSEM_STATSEM_INFO 操作由 ipcs(8) 程序用于提供有关已分配资源的信息。将来可能会修改或移动到 /proc 文件系统接口。

struct semid_ds 中的各个字段在 Linux 2.2 下是短整型,在 Linux 2.4 下已成为长整型。为了利用这一点,在 glibc-2.1.91 或更高版本下重新编译就足够了。(内核通过 cmd 中的 IPC_64 标志区分旧调用和新调用。)

在 glibc 的某些早期版本中,semun 联合体在 <sys/sem.h> 中定义,但 POSIX.1-2001 要求调用者定义此联合体。在 定义此联合体的 glibc 版本上,宏 _SEM_SEMUN_UNDEFINED 在 <sys/sem.h> 中定义。

对信号量集的以下系统限制会影响 semctl() 调用

标签描述
SEMVMX semval 的最大值:依赖于实现(32767)。
为了获得更好的可移植性,最好始终使用四个参数调用 semctl()。

在 Linux 下,semctl() 不是系统调用,而是通过系统调用 ipc(2) 实现的。

符合标准

SVr4、POSIX.1-2001。

参见



previous next Printer Friendly

广告


  

广告



广告