FreeRTOS 中的递归互斥量(Recursive Mutex)

1. 递归互斥量的作用

递归互斥量允许 同一个任务多次获取同一个互斥锁,每次获取都会增加锁的持有计数,必须释放相同次数后才能完全解锁。这种机制专为以下场景设计:

  • 嵌套函数调用:同一任务在不同层级的函数中需要重复访问受保护的共享资源。
  • 递归算法:任务在执行递归逻辑时需要确保资源独占。

示例场景

void funcA() {
    xSemaphoreTakeRecursive(xMutex, portMAX_DELAY); // 第一次获取
    // 访问共享资源
    funcB(); // 嵌套调用 funcB
    xSemaphoreGiveRecursive(xMutex); // 释放
}

void funcB() {
    xSemaphoreTakeRecursive(xMutex, portMAX_DELAY); // 第二次获取(允许)
    // 访问共享资源
    xSemaphoreGiveRecursive(xMutex); // 释放
}

2. 递归互斥量的实现

FreeRTOS 的递归互斥量通过 持有计数(Hold Count)持有任务标识(Holder Task) 实现:

  • 持有计数:记录锁被当前任务获取的次数。
  • 持有任务:仅允许持有锁的任务重复获取。
关键函数
函数功能
xSemaphoreCreateRecursiveMutex()创建递归互斥量
xSemaphoreTakeRecursive()递归获取锁(需配合递归互斥量)
xSemaphoreGiveRecursive()递归释放锁

3. 使用方法

步骤 1:创建递归互斥量
#include "FreeRTOS.h"
#include "semphr.h"

SemaphoreHandle_t xRecursiveMutex;

void main() {
    xRecursiveMutex = xSemaphoreCreateRecursiveMutex();
    configASSERT(xRecursiveMutex != NULL); // 确保创建成功
}
步骤 2:递归获取与释放
void TaskFunction(void *pvParameters) {
    while (1) {
        // 第一次获取
        if (xSemaphoreTakeRecursive(xRecursiveMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
            // 第二次获取(允许)
            if (xSemaphoreTakeRecursive(xRecursiveMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
                // 访问共享资源
                xSemaphoreGiveRecursive(xRecursiveMutex); // 释放第二次
            }
            xSemaphoreGiveRecursive(xRecursiveMutex); // 释放第一次
        }
        vTaskDelay(pdMS_TO_TICKS(10));
    }
}

4. 注意事项

  1. 必须成对使用递归函数
    使用 xSemaphoreTakeRecursive()xSemaphoreGiveRecursive(),禁止混用普通互斥量函数(如 xSemaphoreTake())。

  2. 优先级继承机制
    FreeRTOS 的递归互斥量支持优先级继承(需配置 configUSE_MUTEXES = 1),防止优先级反转。

  3. 资源泄漏风险
    若获取和释放次数不匹配,会导致锁无法释放,其他任务永久阻塞。

    // 错误示例:获取两次但只释放一次
    xSemaphoreTakeRecursive(xMutex, ...); // Hold count = 1
    xSemaphoreTakeRecursive(xMutex, ...); // Hold count = 2
    xSemaphoreGiveRecursive(xMutex);      // Hold count = 1 → 锁未完全释放!
    
  4. 死锁场景

    • 跨任务递归:任务A持有锁时,任务B尝试获取 → 触发阻塞。
    • 非递归互斥量:普通互斥量被同一任务重复获取会导致立即死锁。

5. 递归互斥量 vs 普通互斥量

特性递归互斥量普通互斥量
同一任务重复获取允许(计数递增)导致死锁
释放要求必须释放相同次数只需释放一次
适用场景嵌套/递归调用单次获取释放
函数接口TakeRecursive/GiveRecursiveTake/Give

6. 配置要求

FreeRTOSConfig.h 中确保启用以下宏定义:

#define configUSE_RECURSIVE_MUTEXES     1  // 启用递归互斥量
#define configUSE_MUTEXES               1  // 启用互斥量(依赖项)

7. 性能与资源开销

  • 内存占用:每个递归互斥量比普通互斥量多占用约 4 字节(存储持有计数)。
  • 时间开销:递归操作的时间复杂度为 O(1),但嵌套次数过多可能影响实时性。

通过合理使用递归互斥量,可以安全地在嵌套或递归代码中管理共享资源,但需严格遵守获取/释放的对称性以避免死锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指令集诗人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值