【FreeRTOS】任务间通讯3:互斥量- Mutex
想象一下这样的场景:几个任务像饿狼一样盯着同一块"肥肉"(共享资源),如果不加以控制,结果会怎样?数据被改得面目全非,系统行为变得莫名其妙——这就是典型的多任务"修罗场"!
在FreeRTOS的多任务世界里,共享资源就像公司里唯一的打印机:
当财务部正在打印工资单时...
市场部突然插队打印宣传册...
结果?工资单上可能印满了产品广告
互斥量(Mutex)!它就像资源的"独享VIP卡
一、互斥量简介
互斥量(Mutex, Mutual Exclusion)是FreeRTOS中用于任务间同步的一种机制,主要用于保护共享资源,防止多个任务同时访问同一资源导致的数据不一致问题。互斥量是一种特殊的二进制信号量,具有优先级继承机制,可以有效解决优先级反转问题。
二、互斥量的作用
资源保护:确保同一时间只有一个任务可以访问共享资源
解决竞争条件:防止多个任务同时修改共享数据导致的不一致
优先级继承:当高优先级任务因等待低优先级任务持有的互斥量而阻塞时,低优先级任务会临时继承高优先级任务的优先级
线程安全:实现关键代码段的互斥访问
三、互斥量API接口
1. 创建互斥量
SemaphoreHandle_t xSemaphoreCreateMutex( void );
参数:无
返回值:成功返回互斥量句柄,失败返回NULL
2. 获取互斥量
BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
参数:
xSemaphore
:互斥量句柄xTicksToWait
:等待时间(单位:时钟节拍),可使用portMAX_DELAY
表示无限等待
返回值:
pdPASS
:成功获取互斥量pdFAIL
:获取失败(超时)
3. 释放互斥量
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );
参数:
xSemaphore
:互斥量句柄
返回值:
pdPASS
:成功释放互斥量pdFAIL
:释放失败(通常表示当前任务不持有该互斥量)
4. 删除互斥量
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
参数:
xSemaphore
:要删除的互斥量句柄
四、应用Demo实例
以下是一个使用互斥量保护共享资源的示例:
#include "FreeRTOS.h" #include "task.h" #include "semphr.h"// 共享资源 static int sharedCounter = 0;// 互斥量句柄 SemaphoreHandle_t xMutex;// 任务1:增加计数器 void vTask1(void *pvParameters) {while(1) {// 获取互斥量if(xSemaphoreTake(xMutex, portMAX_DELAY) == pdPASS) {// 临界区开始sharedCounter++;printf("Task1: Counter = %d\n", sharedCounter);// 临界区结束// 释放互斥量xSemaphoreGive(xMutex);}vTaskDelay(pdMS_TO_TICKS(100));} }// 任务2:减少计数器 void vTask2(void *pvParameters) {while(1) {// 获取互斥量if(xSemaphoreTake(xMutex, portMAX_DELAY) == pdPASS) {// 临界区开始sharedCounter--;printf("Task2: Counter = %d\n", sharedCounter);// 临界区结束// 释放互斥量xSemaphoreGive(xMutex);}vTaskDelay(pdMS_TO_TICKS(150));} }int main(void) {// 创建互斥量xMutex = xSemaphoreCreateMutex();if(xMutex == NULL) {printf("Mutex creation failed!\n");return -1;}// 创建任务xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 2, NULL);xTaskCreate(vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL);// 启动调度器vTaskStartScheduler();// 正常情况下不会执行到这里while(1);return 0; }
五、使用注意事项
获取与释放配对:每次成功获取互斥量后必须释放,否则会导致其他任务永久阻塞
避免死锁:
* 不要嵌套获取同一个互斥量
* 获取多个互斥量时保持一致的顺序
3.临界区最小化:保持临界区代码尽可能短,避免长时间持有互斥量
4.优先级继承:理解互斥量的优先级继承机制,合理设置任务优先级
5.不要用于ISR:互斥量不能在中断服务例程中使用(使用信号量替代)
6.资源释放:动态创建的互斥量在使用完毕后应删除以释放内存
7.递归互斥量:对于需要递归获取的情况,使用xSemaphoreCreateRecursiveMutex()
六、小结
FreeRTOS的互斥量是保护共享资源的有效工具,具有以下特点:
提供对共享资源的独占访问
内置优先级继承机制,减少优先级反转的影响
使用简单,API接口清晰
适用于任务间的同步,但不适用于中断服务例程
正确使用互斥量可以显著提高系统的稳定性和可靠性,但需要注意避免常见的陷阱如死锁、优先级反转等问题。在实际应用中,应根据具体场景选择合适的同步机制,平衡系统性能和资源保护的需求。