简介
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
|