1. 什么是信号量
让多个进程(或线程,本文中的进程跟线程不做区分,对进程的应用场景也可以使用在线程上)通过一个特殊变量来进行交互,一个进程在某个关键点上被迫停止执行直到接受到某个特殊变量值。通过这一措施,任何复杂的进程交互都可得到满足,这种特殊的变量就是信号量。
信号量可以看成是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中负责数据操作的互斥、同步等功能。
即:信号量就是一种特殊变量,其本质就是一种变量。
信号量机制由荷兰学者Edsger Dijkstra在1965年提出。
2. 为什么要使用信号量
为了防止出现因多个进程同时访问一个共享资源而引发的一系列问题,我们需要一种方法,在任一时刻只能有一个进程访问代码的临界区域(临界区是指访问临界资源的那部分代码,临界资源是指一次仅允许一个进程使用的资源)。
每个进程中访问临界资源的那段程序代码称为临界区,它需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。
3. 信号量分类
信号量一般分为两类:
一般信号量
信号量s为一个记录型数据结构,其中value为整型变量,系统初始化时为其赋值,PV操作的原语描述如下:
P:P是荷兰语Passeren(通过)的缩写,将信号量s的value值减一,若结果小于零,则执行P操作的进程被堵塞,若结果大于等于零,则执行P操作的进程继续执行。
V:V是荷兰语Vrijgeven(释放)的缩写,将信号量s的value值加一,若结果不大于零,则执行V操作的进程从信号量s相关的list队列中释放一个进程,使其转化为就绪态,自己则继续执行。若结果大于零,则执行V操作的进程继续执行。
二值信号量
信号量s为一个记录型数据结构,其value值只能取值为零或一,二值信号量PV操作的原语描述与一般信号量相同。
在实际简单项目开发中,二值信号量的使用场景要多于一般信号量。
4. 信号量操作
每个标准对信号量的实现提供了不同的方法,但基本的操作由信号量语义提出。针对信号量有四个操作,分别为:
1. 初始化(initialize),也叫做建立(create);
2. 等信号(wait),也可叫做挂起(suspend),即P操作;
3. 给信号(signal)或发信号(post),即V操作;
4. 清理(destroy)。
在实际的项目开发中,信号量的使用要针对当前的操作系统所支持的协议标准类型来使用,不同的协议标准所支持的信号量操作不同,具体的实现方式也不一致,但对于支持同一标准的不同操作系统,所提供的信号量接口是一致的。
本模块后续章节将针对具体的协议标准下的不同操作系统所实现的信号量接口进行说明。