信号量基本操作函数用法

来源:互联网 发布:landsat数据预处理 编辑:程序博客网 时间:2024/05/29 15:26

int semget(key_t _key ,int _nsems,int _semflg);
功能:创建一个新的信号量或获取一个已经存在的信号量的键值。
返回值:成功返回信号量的标识码ID。失败返回-1;
参数:
_key 为整型值,用户可以自己设定。有两种情况:
1. 键值是IPC_PRIVATE,该值通常为0,意思就是创建一个仅能被进程进程给我的信号量。
2. 键值不是IPC_PRIVATE,我们可以指定键值,例如1234;也可以一个ftok()函数来取得一个唯一的键值。
_nsems 表示初始化信号量的个数。比如我们要创建一个信号量,则该值为1.,创建2个就是2。
_semflg :信号量的创建方式或权限。有IPC_CREAT,IPC_EXCL。
IPC_CREAT如果信号量不存在,则创建一个信号量,否则获取。
IPC_EXCL只有信号量不存在的时候,新的信号量才建立,否则就产生错误。

semop

semid:信号集的识别码,可通过semget获取。

sops:指向存储信号操作结构的指针数组,信号操作结构的原型如下

struct sembuf

{

unsigned short sem_num; /* semaphore number */

short sem_op; /* semaphore operation */

short sem_flg; /* operation flags */

};

这三个字段的意义分别为:

sem_num:操作信号在信号集中的编号,第一个信号的编号是0。

sem_op:如果其值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值。通常用于获取资源的使用权;如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。

sem_flg:信号操作标志,可能的选择有两种

IPC_NOWAIT //对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息。

SEM_UNDO //程序结束时(不论正常或不正常),保证信号值会被重设为semop()调用前的值。这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。

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


函数声明
#include <sys/sem.h>


int semctl(int semid, int semnum, int cmd, ... );
描述
semctl() 在 semid 标识的信号量集上,或者该集合的第 semnum 个信号量上执行 cmd 指定的控制命令。(信号量集合索引起始于零。)
根据 cmd 不同,这个函数有三个或四个参数。当有四个参数时,第四个参数的类型是 union semun。调用程序必须按照下面方式定义这个联合体:
union semun { 
         int val;               // SETVAL使用的值   
         struct semid_ds *buf;  // IPC_STAT、IPC_SET 使用缓存区
         unsigned short *array; // GETALL,、SETALL 使用的数组 
         struct seminfo *__buf; // IPC_INFO(Linux特有) 使用缓存区 
}; 
注意:该联合体没有定义在任何系统头文件中,因此得用户自己声明。
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.uid、sem_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) 
};
semmsl、semmns、semopm 和 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 的信号量集合的标识。
所有其它 cmd 成功时返回值 0。




原创粉丝点击