信号量
什么是信号量呢?
信号量的本质是一种数据操作锁,它本身不具备数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中负责数据操作的互斥、同步等功能。
当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用。大于0,资源可以请求,等于0,无资源可用,进程会进入睡眠状态直至资源可用。
当进程不再使用一个信号量控制的共享资源时,信号量的值+1,对于信号量的值进行的增减操作均为原子操作,这是因为信号量主要的作用是维护资源的互斥或多进程的同步访问。而在信号量的创建和初始化上,不能保证操作均为原子性。
为什么要使用信号量?
为了防止因为多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,他可以通过生成并使用令牌授权,在任一时刻只能有一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占的执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问,也就是说信号量是用来调协进程对共享资源的访问的。其中共享内存的使用就要用到信号量。
信号量的工作原理
由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:
P(sv):如果sv的值大于0,就给他减1;如果值等于0,就挂起该进程的执行
V(sv):如果有其他进程因等待sv而被挂起,就让他恢复运行,如果没有进程因等待sv而挂起,就给他加1;
Linux的信号量机制
Linux提供了一组精心设计的信号量接口来对信号量进行操作,它们不只是针对二进制信号量,下面将会对这些函数进行介绍,但请注意,这些函数都是用来对成组的信号量值进行操作的。它们声明在头文件sys/sem.h中。
1.semget()函数
semget(得到一个信号量集标识符或创建一个信号量集对象) |
||
所需头文件 |
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> |
|
函数说明 |
得到一个信号量集标识符或创建一个信号量集对象并返回信号量集标识符 |
|
函数原型 |
int semget(key_t key, int nsems, int semflg) |
|
函数传入值 |
key |
0(IPC_PRIVATE):会建立新信号量集对象 |
大于0的32位整数:视参数semflg来确定操作,通常要求此值来源于ftok返回的IPC键值 |
||
nsems |
创建信号量集中信号量的个数,该参数只在创建信号量集时有效 |
|
msgflg |
0:取信号量集标识符,若不存在则函数会报错 |
|
IPC_CREAT:当semflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的信号量集,则新建一个信号量集;如果存在这样的信号量集,返回此信号量集的标识符 |
||
IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key |