[经验分享] FreeRTOS 信号量与互斥量

[复制链接]
922|0
晓伍 发表于 2025-8-15 07:37 | 显示全部楼层 |阅读模式
简介
1.信号量(Semaphore)
定义:信号量是一种​轻量级的同步机制​,用于控制对共享资源的访问或通知任务之间的状态变化。
类型:




2.互斥量(Mutex)

定义:互斥量(Mutex)是一种特殊的信号量,用于​保护共享资源​,确保同一时间只有一个任务可以访问该资源。

特点:
独占性​:同一时刻只能有一个任务持有互斥量。
优先级继承​(可选):如果高优先级任务等待低优先级任务释放互斥量,系统会暂时提升低优先级任务的优先级,避免优先级倒置问题。

3.信号量与互斥量的作用




信号量(Semaphore)
1.常用 API 函数




2.信号量的创建与使用

2.1二值信号量创建:

SemaphoreHandle_t xBinarySemaphore = xSemaphoreCreateBinary();


2.2计数信号量

SemaphoreHandle_t xCountingSemaphore = xSemaphoreCreateCounting(10, 0); // 初始值为0,最大值为10


2.3递归互斥量

SemaphoreHandle_t xRecursiveMutex = xSemaphoreCreateRecursiveMutex();


2.4获取信号量,阻塞式获取(等待信号量)

xSemaphoreTake(xSemaphore, portMAX_DELAY); // 永久等待


2.5获取信号量,非阻塞式获取

if (xSemaphoreTake(xSemaphore, 0) == pdTRUE) {
  // 成功获取信号量
} else {
  // 无法获取信号量
}


2.6释放二值信号量或计数信号量

xSemaphoreGive(xSemaphore);


2.7释放递归互斥量

xSemaphoreGiveRecursive(xRecursiveMutex);


2.8在中断服务程序中获取信号量

xSemaphoreTakeFromISR
(
  SemaphoreHandle_t xSemaphore,
  signed BaseType_t *pxHigherPriorityTaskWoken
)


2.9在中断服务程序中释放信号量

xSemaphoreGiveFromISR
(
  SemaphoreHandle_t xSemaphore,
  signed BaseType_t *pxHigherPriorityTaskWoken
)


互斥量(Mutex)
1.常用API函数




2.互斥量的创建与使用

2.1互斥量的创建

SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();


注意:在 FreeRTOS 中,建议使用 xSemaphoreCreateMutex() 而不是 xSemaphoreCreateBinary() 来创建互斥量,因为前者支持优先级继承,避免死锁问题。

2.2获取互斥量(Lock)

BaseType_t xResult = xSemaphoreTake(xMutex, portMAX_DELAY);


参数说明:
xMutex:互斥量句柄。
portMAX_DELAY:无限等待,直到获取到互斥量。
其他等待时间(如 pdMS_TO_TICKS(100))可设置为超时时间。

2.3释放互斥量(Unlock)

xSemaphoreGive(xMutex);


信号量与互斥量的区别
1.功能差异




2.使用场景对比

信号量适用场景:

通知任务事件发生(如中断完成、数据到达等)。
控制任务的执行顺序(如任务 A 等待任务 B 的信号)。
资源池管理(如缓冲区数量有限时)。
互斥量适用场景:

保护共享资源(如全局变量、硬件寄存器等)。
防止多任务同时访问共享资源导致的数据不一致问题。
递归访问共享资源(如嵌套函数调用中访问同一资源)。
示例代码
1.信号量示例

#include "FreeRTOS.h"
#include "semphr.h"

SemaphoreHandle_t xSemaphore;

void vTaskFunction(void *pvParameters) {
    // 获取信号量
    if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
        // 执行操作
    }
}

void vInterruptHandler(void) {
    // 发送信号量
    xSemaphoreGiveFromISR(xSemaphore, NULL);
}



2.互斥量示例

include "FreeRTOS.h"
#include "semphr.h"

SemaphoreHandle_t xMutex;

void vTaskFunction(void *pvParameters) {
    // 获取互斥量
    if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
        // 访问共享资源
        // ...
        // 释放互斥量
        xSemaphoreGive(xMutex);
    }
}




常见问题与注意事项
1.死锁问题

1.1死锁的四个必要条件:
互斥(Mutual Exclusion):资源不能被同时访问
​占有并等待(Hold and Wait):任务持有至少一个资源,并等待其他资源。
不可抢占(No Preemption):资源只能由持有它的任务释放。
循环等待(Circular Wait):存在一个任务链,每个任务都在等待下一个任务所持有的资源。
1.2引发死锁的常见情况:
多个互斥量的错误获取顺序
在中断服务程序中使用互斥量
不正确的超时设置
2.优先级翻转问题

优先级翻转是指在一个多任务系统中,一个高优先级的任务被低优先级的任务阻塞,从而无法执行其任务的情况。
FreeRTOS 提供了 优先级继承(Priority Inheritance) 机制来解决优先级翻转问题
3.资源释放与管理

3.1信号量的释放 应当始终在相同的任务或中断上下文中进行。
​3.2避免资源泄漏​:确保每次 xSemaphoreTake() 都有对应的 xSemaphoreGive()。
3.3合理设置超时时间​:在调用 xSemaphoreTake() 时,设置合适的超时时间以防止任务长时间阻塞。
————————————————
版权声明:本文为CSDN博主「谱写秋天」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42222415/article/details/150346008

您需要登录后才可以回帖 登录 | 注册

本版积分规则

108

主题

4389

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部