信号量
定义
信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端。确认这些信号量VI引用的是初始创建的信号量。
1) 创建/获取信号量
int semget (key_t key, int nsems, int semflg);
A. 该函数以key参数为键值创建一个信号量集合(nsems参数表示集合中的信号量数),
或获取已有的信号量集合(nsems取0)
B. semflg取值:
0 - 获取,不存在即失败。
**IPC_CREAT** - 创建,不存在即创建,已存在即获取,除非…
**IPC_EXCL** - 排斥,已存在即失败。
C. 成功返回信号量集合标识,失败返回-1。
2) 操作信号量
int semop (int semid, struct sembuf* sops,unsigned nsops);
A. 该函数对semid参数所标识的信号量集合中,由sops参数所指向的包含nsops个元素的,
结构体数组中的每个元素,依次执行如下操作:
a) 若sem_op大于0,则将其加到第sem_num个信号量的计数值上,以表示对资源的释放;
b) 若sem_op小于0,则从第sem_num个信号量的计数值中减去其绝对值,以表示对资源的获取;
c) 若第sem_num个信号量的计数值不够减(信号量不能为负),则此函数会阻塞,
直到该信号量够减为止,以表示对资源的等待;
d) 若sem_flg包含IPC_NOWAIT位,则当第sem_num个信号量的计数值不够减时,
此函数不会阻塞,而是返回-1,errno为EAGAIN,以便在等待资源的同时还可做其它处理;
e) 若sem_op等于0,则直到第sem_num个信号量的计数值为0时才返回,
除非sem_flg包含 IPC_NOWAIT位。
3) 销毁/控制信号量
int semctl (int semid, int semnum, int cmd);
int semctl (int semid, int semnum, int cmd,union semun arg);
cmd取值: IPC_STAT
获取信号量集合的属性,通过arg.buf输出。
IPC_SET
设置信号量集合的属性,通过arg.buf输入,仅以下四个属性可设置:
semid_ds::sem_perm.uid
semid_ds::sem_perm.gid
semid_ds::sem_perm.mode
IPC_RMID
立即删除信号量集合。
此时所有阻塞在对该信号量集合的,semop函数调用,都会立即返回失败,errno为EIDRM。
GETALL
获取信号量集合中每个信号量的计数值,通过arg.array输出。
SETALL
设置信号量集合中每个信号量的计数值,通过arg.array输入。
GETVAL
获取信号量集合中,第semnum个信号量的计数值,通过返回值输出。
SETVAL
设置信号量集合中,第semnum个信号量的计数值,通过arg.val输入。
范例
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <stdbool.h>
#define N 4
short int nums[N] = {
3,3,3,3};
int main()
{
key_t key = ftok("/",111);
if(key == -1)
{
perror("ftok");
return