本章节开始讲解 FreeRTOS 任务间的同步和资源共享机制,计数信号量。 FreeRTOS 中计数信号量的源码实现是基于消息队列实现的。
信号量的概念及其作用
信号量(semaphores)是 20 世纪 60 年代中期 Edgser Dijkstra 发明的。 使用信号量的最初目的是
为了给共享资源建立一个标志,该标志表示该共享资源被占用情况。这样,当一个任务在访问共享资源之
前,就可以先对这个标志进行查询,从而在了解资源被占用的情况之后,再来决定自己的行为。
实际的应用中,信号量的作用又该如何体现呢?比如有个 30 人的电脑机房,我们就可以创建信号量
的初始化值是 30,表示 30 个可用资源,不理解的初学者表示信号量还有初始值?是的,信号量说白了就
是共享资源的数量。 另外我们要求一个同学使用一台电脑,这样每有一个同学使用一台电脑,那么信号量
的数值就减一,直到 30 台电脑都被占用,此时信号量的数值就是 0。 如果此时还有几个同学没有电脑可
以使用,那么这几个同学就得等待,直到有同学离开。 有一个同学离开,那么信号量的数值就加 1,有两
个就加 2,依此类推。刚才没有电脑用的同学此时就有电脑可以用了,有几个同学用,信号量就减几,直
到再次没有电脑可以用,这么一个过程就是使用信号量来管理共享资源的过程。
平时使用信号量主要实现以下两个功能:
? 两个任务之间或者中断函数跟任务之间的同步功能,这个和前面章节讲解的事件标志组是类似的。其
实就是共享资源为 1 的时候。
? 多个共享资源的管理,就像上面举的机房上机的例子。
针对这两种功能,FreeRTOS 分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数
信号量的一种特殊形式,即初始化为仅有一个资源可以使用,只不过 FreeRTOS 对这两种都提供了 API
函数,而像 RTX,uCOS-II 和 III 是仅提供了一个信号量功能,设置不同的初始值就可以分别实现二值信
号量和计数信号量。 当然,FreeRTOS 使用计数信号量也能够实现同样的效果。
实际上信号量还有很多其它用法,而且极具挑战性,可以大大的开拓大家的视野,有兴趣的同学可以
阅读一下《The Little Book Of Semaphores》 ,作者是 Allen B. Downy。
FreeRTOS 任务间计数信号量的实现
任务间信号量的实现是指各个任务之间使用信号量实现任务的同步或者资源共享功能。 下面我们通过
如下的框图来说明一下 FreeRTOS 计数信号量的实现,让大家有一个形象的认识。
运行条件:
? 创建 2 个任务 Task1 和 Task2。
? 创建计数信号量可用资源为 1。
运行过程描述如下:
? 任务 Task1 运行过程中调用函数 xSemaphoreTake 获取信号量资源,如果信号量没有被任务 Task2
占用,Task1 将直接获取资源。 如果信号量被 Task2 占用,任务 Task1 将由运行态转到阻塞状态,
等待资源可用。一旦获取了资源并使用完毕后会通过函数 xSemaphoreGive 释放掉资源。
? 任务 Task2 运行过程中调用函数 xSemaphoreTake 获取信号量资源,如果信号量没有被任务 Task1
占用,Task2 将直接获取资源。 如果信号量被 Task1 占用,任务 Task2 将由运行态转到阻塞状态,
等待资源可用。一旦获取了资源并使用完毕后会通过函数 xSemaphoreGive 释放掉资源。