互斥信号量相关的 API 函数详解

FreeRTOS 中的互斥信号量(Mutex Semaphore)是一种特殊的二值信号量,专为解决资源互斥访问和优先级反转问题设计。其核心特性是支持优先级继承(Priority Inheritance),当高优先级任务因等待低优先级任务持有的互斥量而阻塞时,低优先级任务会临时继承高优先级任务的优先级。以下是互斥信号量相关的 API 函数详解,包括动态和静态创建两种方式。


1. 动态创建互斥信号量

函数原型
SemaphoreHandle_t xSemaphoreCreateMutex(void);
  • 功能:动态分配内存并初始化一个互斥信号量。
  • 参数:无。
  • 返回值
    • 成功:返回互斥量句柄(SemaphoreHandle_t)。
    • 失败:返回 NULL(内存不足时)。
  • 特点
    • 初始状态为 可用(计数值为 1,可直接获取)。
    • 需确保 FreeRTOS 堆内存足够(通过 configTOTAL_HEAP_SIZE 配置)。
    • 支持优先级继承(需配置 configUSE_MUTEXES = 1)。
示例代码
SemaphoreHandle_t xMutex = NULL;

void vTaskExample(void) {
    // 动态创建互斥信号量
    xMutex = xSemaphoreCreateMutex();
    if (xMutex != NULL) {
        // 创建成功
    }
}

2. 静态创建互斥信号量

函数原型
SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t *pxMutexBuffer);
  • 功能:使用用户预先分配的静态内存初始化互斥信号量。
  • 参数
    • pxMutexBuffer:指向 StaticSemaphore_t 类型变量的指针,用于存储互斥量内部数据。
  • 返回值
    • 成功:返回互斥量句柄。
    • 失败:返回 NULL(参数无效时)。
  • 特点
    • 初始状态为 可用
    • 需预先分配 StaticSemaphore_t 结构体内存(全局或静态变量)。
示例代码
StaticSemaphore_t xMutexBuffer;
SemaphoreHandle_t xMutex = NULL;

void vTaskExample(void) {
    // 静态创建互斥信号量
    xMutex = xSemaphoreCreateMutexStatic(&xMutexBuffer);
    if (xMutex != NULL) {
        // 创建成功
    }
}

3. 获取(Take)互斥量

函数原型
BaseType_t xSemaphoreTake(
    SemaphoreHandle_t xSemaphore,
    TickType_t xTicksToWait // 阻塞时间
);
  • 功能:尝试获取互斥量。若已被占用,任务将阻塞等待。
  • 参数
    • xSemaphore:互斥量句柄。
    • xTicksToWait:阻塞时间(单位:系统节拍)。portMAX_DELAY 表示无限等待(需配置 INCLUDE_vTaskSuspend=1)。
  • 返回值
    • pdTRUE:成功获取互斥量。
    • pdFALSE:超时或参数无效。
  • 关键规则
    • 必须由获取互斥量的任务释放互斥量(不可跨任务释放)。

4. 释放(Give)互斥量

函数原型
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
  • 功能:释放互斥量,允许其他任务获取。
  • 参数
    • xSemaphore:互斥量句柄。
  • 返回值
    • pdPASS:释放成功。
    • pdFAIL:释放失败(当前任务未持有该互斥量)。
  • 注意
    • 必须由持有互斥量的任务调用此函数。

5. 删除互斥量

函数原型
void vSemaphoreDelete(SemaphoreHandle_t xSemaphore);
  • 功能:删除互斥量并释放内存(仅对动态创建的互斥量有效)。
  • 参数
    • xSemaphore:互斥量句柄。
  • 注意
    • 删除前需确保无任务持有该互斥量,否则可能导致未定义行为。

使用场景示例

保护共享资源
SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();

// 任务 A 访问共享资源
void vTaskA(void *pvParameters) {
    while (1) {
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
            // 安全访问共享资源
            // ...
            xSemaphoreGive(xMutex); // 释放互斥量
        }
        vTaskDelay(10);
    }
}

// 任务 B 访问共享资源
void vTaskB(void *pvParameters) {
    while (1) {
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
            // 安全访问共享资源
            // ...
            xSemaphoreGive(xMutex); // 释放互斥量
        }
        vTaskDelay(10);
    }
}

注意事项

  1. 优先级继承

    • 互斥量自动启用优先级继承,无需额外配置(需 configUSE_MUTEXES = 1)。
    • 当高优先级任务等待低优先级任务释放互斥量时,低优先级任务会临时继承高优先级任务的优先级。
  2. 不可跨任务释放

    • 必须由获取互斥量的任务释放,否则会导致 xSemaphoreGive 返回 pdFAIL
  3. 递归互斥量

    • 若任务需多次获取同一互斥量,应使用递归互斥量xSemaphoreCreateRecursiveMutex()),并通过 xSemaphoreTakeRecursive()xSemaphoreGiveRecursive() 操作。
  4. 中断中不可使用

    • 互斥量不能在中断服务程序(ISR)中获取或释放(无 FromISR 版本)。
  5. 死锁风险

    • 避免同一任务多次获取互斥量(除非使用递归互斥量)。
    • 确保互斥量释放逻辑在所有代码路径中执行(如使用 gotoreturn 前释放)。

互斥量 vs 二值信号量

特性互斥量二值信号量
初始值1(可用)0(不可用)
释放者必须由获取者释放任意任务或中断均可释放
优先级继承支持不支持
适用场景保护共享资源,防止优先级反转任务同步或简单事件通知

通过合理使用互斥信号量,可确保共享资源的安全访问,避免数据竞争和优先级反转问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

九层指针

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

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

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

打赏作者

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

抵扣说明:

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

余额充值