semctl函数

604 篇文章 8 订阅
579 篇文章 5 订阅
信号量集

当利用信号量机制解决了单个资源的互斥访问后,我们讨论如何控制同时需要多个资源的互斥访问。信号量集是指同时需要多个资源时的信号量操作。

一般来说,我们也可以把各进程之间发送的消息作为信号量看待。

与进程互斥时不同的是,这里的信号量只与制约进程及被制约进程有关而不是与整组并发进程有关。因此,我们称该信号量为私用信号量(Private Semaphore)。

一个进程Pi的私用信号量Semi是从制约进程发送来的进程Pi的执行条件所需要的消息。

互斥时使用的信号量为公用信号量

----------------------------------------------------我是分隔线-------------------------------------------------

semctl函数对一个信号量执行各种控制操作。


函数声明

------------------------------------------------------------------------------------
#include <sys/sem.h>

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

描述

semctl() 在 semid 标识的信号量集上,或者该集合的第semnum 个信号量上执行 cmd 指定的控制命令。(信号量集合索引起始于零。)

根据 cmd 不同,这个函数有三个或四个参数。当有四个参数时,第四个参数的类型是 unionsemun调用程序 必须按照下面方式定义这个联合体:

union semun
         int              val;               // SETVAL使用的值   
         struct semid_ds *buf;  // IPC_STAT、IPC_SET 使用缓存区
         unsigned short  *array;  // GETALL,、SETALL 使用的数组 
         struct seminfo  *__buf;  // IPC_INFO(Linux特有) 使用缓存区 
}; 
注意:该联合体没有定义在任何系统头文件中,因此得用户自己声明。(centos6.5中/linux/sem.h可以找到)

semid_ds 数据结构在头文件 <sys/sem.h> 有如下定义:
struct semid_ds
       struct ipc_perm sem_perm;   // 所有者和权限
       time_t          sem_otime;           // 上次执行 semop 的时间  
       time_t          sem_ctime;           // 上次更新时间 
       unsigned short  sem_nsems;   // 在信号量集合里的索引
 };

结构体 ipc_perm 在头文件 <sys/ipc.h>
中的定义如下(高亮的字段可以使用 IPC_SET 设置):
struct ipc_perm
       key_t          __key;    // 提供给 semget()的键 
       uid_t          uid;      // 所有者有效 UID  
       gid_t          gid;      // 所有者有效 GID 
       uid_t          cuid;     // 创建者有效 UID 
       gid_t          cgid;     // 创建者有效 GID
       unsigned short mode;     // 权限 
       unsigned short __seq;    // 序列号
}; 
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位)。调用进程的有效用户ID必须匹配信号量集合的所有者(sem_perm.uid)或创建者(sem_perm.cuid),或者调用者必须有特权。参数semnum 被忽略。
IPC_RMID
立即删除信号量集合,唤醒所有因调用semop()  阻塞在该信号量集合里的所有进程(相应调用会返回错误且 errno被设置为 EIDRM)。调用进程的有效用户ID必须匹配信号量集合的创建者或所有者,或者调用者必须有特权。参数semnum 被忽略。
IPC_INFO (Linux 定义的)
通过 arg.buf 指向的结构返回系统范围内的信号量限制和参数。这个结构的类型是seminfo,如果宏 _GNU_SOURCE 特性宏被定义,则该结构定义在头文件<sys/sem.h>
struct  seminfo
     int semmap;  // 信号量映射里的条数,内核未使用 
     int semmni;  // 信号量集合的最大个数 
     int semmns;  // 在所有信号量集合里信号量个数上限  
     int semmnu;  // 系统范围内的 undo 结构最大个数,内核未使用 
     int semmsl;  // 一个信号量集合里信号量个数上限 
     int semopm;  // 执行的最大操作个数  
     int semume;  // 每个进程内 undo 结构最大个数,内核未使用
     int semusz;  // 结构 sem_undo 的尺寸 
     int semvmx;  // 信号量值的上限
     int semaem;  // Max. value that can be recorded for
                    semaphore adjustment (SEM_UNDO) 
};

semmslsemmnssemopm semmni 设置可以通过/proc/sys/kernel/sem 更改。


返回值

失败时 semctl() 返回 -1 并设置 errno 指明错误。


否则该系统调用返回一个依赖于 cmd 的非负值:
GETNCNT
semncnt 的值。
GETPID
sempid 的值。
GETVAL
semval 的值。
GETZCNT
semzcnt 的值。
IPC_INFO
内核内部关于所有信号量集合的记录数组的最大索引值。(这个信息可以用于重复执行 SEM_STAT来获得系统内所有信号量集合的信息。)
SEM_INFO
如同 IPC_INFO
SEM_STAT
索引为 semid 的信号量集合的标识。







  • 10
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
semctl函数是Linux系统中用于对信号量进行控制操作的系统调用函数函数原型: ```c #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semctl(int semid, int semnum, int cmd, ...); ``` 参数说明: - `semid`:信号量集标识符; - `semnum`:信号量的编号,从0开始; - `cmd`:控制命令,可以是IPC_RMID(删除信号量集)、IPC_SET(设置信号量集的IPC权限)、IPC_STAT(获取信号量集的状态信息)、GETVAL(获取信号量的值)、SETVAL(设置信号量的值)、GETPID(获取上次执行semop操作的进程ID)、GETNCNT(获取等待该信号量变为非0的进程数)、GETZCNT(获取等待该信号量变为0的进程数); 如果cmd为IPC_SET,则需要传递一个union semun类型的参数。semun结构定义如下: ```c union semun { int val; /* SETVAL命令使用的信号量值 */ struct semid_ds *buf; /* IPC_STAT和IPC_SET命令使用的结构体指针 */ ushort *array; /* GETALL和SETALL命令使用的数组指针 */ }; ``` 函数返回值为执行结果,通常为0表示执行成功,否则表示执行失败。 常用的控制命令如下: - `IPC_RMID`:删除信号量集; - `IPC_SET`:设置信号量集的IPC权限; - `IPC_STAT`:获取信号量集的状态信息; - `GETVAL`:获取信号量的值; - `SETVAL`:设置信号量的值。 需要注意的是,当使用IPC_RMID命令删除一个信号量集时,如果有其他进程正在使用该信号量集,那么这些进程将会收到一个SIGINT信号,即如同按下了Ctrl+C键一样。因此,在删除信号量集之前,需要确保没有其他进程正在使用该信号量集。 另外,当使用SETVAL命令设置信号量的值时,需要将union semun类型的参数中的`val`字段设置为要设置的值。而当使用GETVAL命令获取信号量的值时,需要将union semun类型的参数中的`buf`字段设置为一个`semid_ds`结构体指针,用于存放获取的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值