本文给出创建信号量涉及到的函数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 numbersemnum
toarg.val
IPC_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_op
sem_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.