信号量是操作系统中重要的一部分,信号量一般用来进行资源管理和任务同步。信号量分为二值信号量、计数型信号量、互斥信号量。不同信号量的应用场景也不同,但是有些应用场景是可以互换着使用的。
信号量简介
信号量常常用于控制对共享资源的访问和任务同步。信号量用于控制共享资源访问的场景相当于一个上锁机制,代码只有获得这个锁的钥匙才能执行。信号量也用于任务与任务和中断与任务之间的同步。在执行中断服务函数的时候可以通过向任务发送信号量来通知任务它所期待的事件发生了,当退出中断服务函数以后在任务调度器的调度下同步的任务就会执行。任务和任务之间也可以通过信号量来完成同步。
二值信号量
二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是互斥信号量拥有优先级继承机制,二值信号量没有优先级继承。因此二值信号量更适合用于同步(任务与任务或任务与中断的同步),而互斥信号量适用于简单的互斥访问。
和队列一样,信号量API函数允许设置一个阻塞时间,阻塞时间是当任务获取信号量的时候由于信号量无效从而导致任务进入阻塞态的最大时钟节拍数。如果多个任务同时阻塞在同一个信号量上的话,那么优先级最高的那个任务优先获取信号量,这样当信号量有效的时候高优先级的任务就会解除阻塞状态。
1.xSemaphoreCreateBinary() 二值信号量创建
通过此函数创建二值信号量,信号量所需的RAM是由FreeRTOS动态分配的。此函数创建好的二值信号量默认是空的,也就是说使用xSemaphoreTake()是获取不到的。
函数原型:
#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
参数:无
返回值:
NULL 失败
其他值:创建成功的二值信号量的句柄。
参考例子:
SemaphoreHandle_t xSemaphore = NULL;
xSemaphore = xSemaphoreCreateBinary();
可以看到二值信号量的创建,底层调用函数xQueueGenericCreate()来创建一个类型为queueQUEUE_TYPE_BINARY_SEMAPHORE,长度为1,队列项长度为0的队列。说明二值信号量底层是队列。创建的队列是个没有存储区的队列,使用队列是否为空来表示二值信号量,队列是否为空可以通过队列结构体的成员变量uxMessagesWaiting来判断。
2.xSemaphoreGive()释放二值信号量
此函数用于释放二值信号量、计数型信号量或互斥信号量。
函数原型:
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
参数:
xSemaphore :要释放的信号量句柄
返回值:
pdPASS:释放成功
errQUEUE_FULL:释放失败。
实例:
if( xSemaphoreGive( xSemaphore ) != pdTRUE ) //失败
从代码可以看到释放二值信号量,是向队列入队一个内容为空的队列项。入队后结构体成员变量uxMessagesWaiting会加一,则判断信号量有效。
3.xSemaphoreGiveFromISR()中断释放信号量
此函数用于在中断中释放信号量,此函数只能用来释放二值信号量和技术型信号量,绝对不能用来在中断服务函数中释放互斥信号量。因为互斥信号量涉及到优先级继承的问题,而中断不属于任务,无法处理中断优先级继承。
函数原型:
#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) )
参数:
xSemaphore:要释放的信号量句柄
pxHigherPriorityTaskWoken:退出中断以后是否进行任务切换。如果此值为pdTRUE,在对出中断服务函数之前一定要进行一次任务切换。该参数判断“信号量唤醒的任务”优先级是否高于“当前被中断的任务”。
返回值:
pdPASS:释放成功
errQUEUE_FULL:释放失败
实例:
static BaseType_t xHigherPriorityTaskWoken;

本文详细介绍了操作系统中的信号量概念,包括二值信号量、计数型信号量和互斥信号量的区别与应用场景,以及它们在任务同步和资源共享中的关键作用。通过实例演示,展示了如何创建、释放和获取这些信号量,以及如何避免优先级翻转问题。
&spm=1001.2101.3001.5002&articleId=123886654&d=1&t=3&u=452056b5be9e41178d2b4dfef2088208)
3490

被折叠的 条评论
为什么被折叠?



