了解了消息队列之后,如果想要深入了解队列创建流程及其API函数(简单地看作帮助传递消息的工具),我们需要从源码开始读起,但是源码中涉及了信号量这一概念,因此必须先将信号量作为必备知识学习一下。
信号量是任务之间进行通信的一种机制(如果有交换机部分的知识的话也可以简单用信令的知识理解一下,两者在通信同步和协调上有点相通但是绝不能划等号),可以实现任务的同步或者资源的互斥访问。信号量有自己的数量限制,一旦数量归零,那么需要这个信号量的任务就会进入阻塞状态。
信号量自己也分很多种类,下面一个个看。
(一)二值信号量
二值信号量,顾名思义,只有两个值,要么1,要么0。也就是说,二值信号量完全可以看作一个只能包含一个消息的消息队列,不是空的,就是满的,但是并不需要知道这里面到底是什么消息,只要知道有没有消息即可。
二值信号量有自己的运行机制,当创建信号量,用户可自定义该信号量个数,二值信号量自然是最多1个。之后任何任务都可以从二值信号量资源中获取一个二值信号量,获取成功则返回正确,获取失败,任务就会按照之前讲过的阻塞时间等待信号量的释放。

注:图中提到的线程是一种基本调度单位,它只具备运行中必不可少的资源,任务可以是个线程。
这么说可能还是有些抽象,下面拿具体实例来说明一下。例如有一个温湿度传感器被设置为一秒钟采集一次数据,而需要用液晶屏去显示采集到的数据,每100ms刷新一次。此时液晶屏就会有多次无效刷新,浪费CPU资源,那么就可以在温湿度传感器采集到数据并发送给液晶屏,数据到达时发一个二值信号量给液晶屏,使它正式工作,而在其他时间使它处于阻塞状态,这样就完成了两个任务间的同步。
(二)计数信号量
计数信号量,肯定就是用来计数的,常用于事件计数或者资源的管理。如果二值信号量看作是一个长度为1的队列,那么计数信号量则是长度大于1的队列,同样,计数信号量也不用去关注队列里面的消息是什么,只要关注里面有没有消息即可。
计数信号量的运行机制也很简单,就是普通的加加减减。每个资源都可以设置一个最大任务数量,这些任务通过获取信号量来获取资源,而每取走一个信号量,计数减一,直到为0时,阻塞试图继续获取资源的任务,直到有其他任务释放信号量。

除了上述两种信号量外,其实还有互斥信号量 和递归信号量,其中互斥信号量更为重要且复杂,下一章会重点讲述。