本文给出创建信号量涉及到的函数API,每个函数都给出超链接,若本文的内容不够清晰,直接点击链接查看原文。
1. 创建一个信号量
使用semget函数创建/打开一个信号量集,
#include <sys/sem.h>
// get a System V semaphore set identifier
int semget(key_t key, int nsems, int semflg);
参数:
key,进程间通信(IPC)键,类型为key_t,实为长整型(在sys/types.h中被定义)nsems,信号量集(union semun)中信号量的个数semflg,如IPC_CREAT | 0660。指定IPC_CREAT,若信号集不存在,则创建一个
返回值:
- on success: the id of a semaphore set (semaphore set IPC identifier)
- on error: -1
1.1 进程间通信键
有两种方法可以标识进程间通信(inter-process communication,IPC)的对象,两者一一对应
- 内部名:标识符ID(identifier),类似于文件描述符,
semget返回的就是标识符 - 外部名:键key,类似于文件名
可能通过ftok函数创建一个IPC键,
#include <sys/ipc.h>
// convert a pathname and a project identifier to a System V IPC key
key_t ftok(const char *pathname, int proj_id);
参数:
pathname: an existing, accessible fileproj_id: must be nonzero
2. 初始化信号量
semget创建一个信号集并没有对其初始化,需要对其初始化,比如锁初始时是开的还是关的。信号量集的定义如下:
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short int *array; /* array for GETALL, SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
使用函数semctl对信号量进行初始化,
#include <sys/sem.h>
// System V semaphore control operations
int semctl(int semid, int semnum, int cmd, ...);
参数:
semid: 信号量集的标识符semnum:[0, nsems-1]cmd: 操作命令SETVAL, Set the value of semaphore numbersemnumtoarg.valIPC_INFO,GETVAL, …
3. 信号量操作
使用函数semop对信号量进行操作,如加锁(值减1)、解锁(值加1)。
#include <sys/sem.h>
// atomic array of operations on a semaphore set
int semop(int semid, struct sembuf *sops, size_t nsops);
参数
semid,信号量集的标识符sops,信号量操作数组nsops,结构体sembuf中的元素个数
3.1 信号量操作数组
sembuf定义如下:
struct sembuf { /*信号量操作数组 */
u_short sem_num; /* semaphore # */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
(1)sem_num
sem_num,指定对信号量集中哪个信号进行操作,从0开始
(2)sem_op
对信号量进行操作,若值为n,大于0,给信号量(理解成资源的个数)加n个,小于0,相当于给资源数目减n。
sem_op> 0,sem_val += sem_opsem_op< 0,sem_val -= |sem_op|sem_op= 0,sem_val = 0
(3)sem_flg
sem_flg有两个取值SEM_UNDO和IPC_NOWAIT。
SEM_UNDO: it will be automatically undone when the process terminates.