文章目录
前言
信号量,我们在之前网络编程的时候就讲过它的详细概念了,感兴趣的朋友可以回顾一下,这里介绍一下其在Freertos中的用法。
一、信号量的基础知识
1.1 信号量与队列的关系
信号量主要的功能就是实现任务之间的同步与互斥,实现的方式主要就是依靠队列(信号量是特殊的队列)的任务阻塞机制。具体来说,信号量就是大小为1的队列,信号量的“获取”和“释放”操作对应着队列的“发送”和“接收”。与此同时这样,我们用于队列的很多函数,也就成信号量的底层函数,例如:xSemaphoreTake()实际上是 xQueueReceive() 的封装;xSemaphoreGive() 是 xQueueSend() 的封装;对于在中断中使用的信号量操作,如xSemaphoreGiveFromISR(),对应的是 xQueueSendFromISR()。
那么为什么我们以及学习了队列还要学习信号量呢?其实还是为了“省”,前面介绍过队列常用来进行数据的传递,但是我们在同步或者互斥的之后却只需要确定队列中还有没有成员。如此一来我们就可以利用信号量来简化代码结构,而无需为信号量的实现单独构建一个冗长的队列。
1.2 优先级反转
优先级反转指的是一个高优先级的任务由于等待某个共享资源,而被迫让位于低优先级的任务,进而导致系统中的中等优先级任务抢占 CPU 资源。这种情况下,系统中的优先级关系被打破,高优先级任务的执行反而延后了。
例如如果任务B(低优先级)持有一个共享资源,任务A(高优先级)试图获取该资源,但任务A无法获取而被阻塞。此时任务C(中优先级)由于优先级高于任务B而获得了CPU的控制权,继续执行,导致任务A无法继续执行,尽管它的优先级高于任务C。最终任务A的执行被任务C延迟,而这个过程违背了优先级调度的原则。
优先级反转会带来系统调度的混乱,尤其在实时系统中,高优先级任务可能是一个时间敏感的任务。如果优先级反转持续存在,它可能导致高优先级任务不能在规定时间内完成,甚至引发系统的故障或崩溃。
为了解决优先级反转问题,操作系统通常引入优先级继承机制,即当一个低优先级任务持有某个共享资源时,如果一个高优先级任务试图访问这个资源并被阻塞,操作系统会将低优先级任务的优先级“继承”为高优先级任务的优先级,直到它释放该资源。这意味着低优先级任务会立即完成其对资源的操作,进而释放资源,使得高优先级任务可以继续执行。
二、FreeRTOS信号量
在FreeRTOS中,信号量(Semaphore)是一种用于管理任务间同步和共享资源的机制,类似于Linux中的信号量机制。它可以用于控制对共享资源(如硬件外设、内存等)的访问,以及任务之间的同步。FreeRTOS的信号量可以分为几种主要类型,每种类型都有不同的应用场景:
- 二元信号量(Binary Semaphore):实现为长度为 1、项大小为 0 的队列。
- 计数信号量(C