信号量核心API函数详细介绍

一、信号量核心概念

信号量是 FreeRTOS 中用于任务间同步、互斥或资源计数的内核对象,主要分为 4 类:

  • 二进制信号量:仅两种状态(可用 / 不可用),适用于单次资源占用或任务同步;
  • 计数信号量:支持 N 个资源计数,适用于多实例资源分配;
  • 互斥信号量:用于任务间互斥访问共享资源,支持优先级继承;
  • 递归互斥信号量:允许同一任务多次获取互斥量,避免自我死锁。

二、通用信号量 API 函数(基础操作)

1. 信号量句柄定义

c

运行

复制代码
SemaphoreHandle_t xSemaphore; // 通用信号量句柄(适用于所有信号量类型)
  • 功能:定义信号量句柄,用于后续操作信号量(创建、获取、释放等);
  • 说明:句柄本质是指向信号量控制块的指针,创建成功后由 API 函数返回。
2. 信号量删除函数

c

运行

复制代码
void vSemaphoreDelete(SemaphoreHandle_t xSemaphore);
  • 功能:删除已创建的信号量,释放其占用的内存(动态创建的信号量需手动删除);
  • 参数:xSemaphore:待删除的信号量句柄;
  • 注意:删除正在被任务等待的信号量会导致等待任务永久阻塞,需确保信号量不再被使用时删除。

三、二进制信号量 API 函数

1. 动态创建二进制信号量

c

运行

复制代码
SemaphoreHandle_t xSemaphoreCreateBinary(void);
  • 功能:动态分配内存,创建一个二进制信号量(初始状态为 "不可用");
  • 返回值:
    • 非 NULL:创建成功,返回信号量句柄;
    • NULL:内存不足,创建失败;
  • 说明:创建后需通过xSemaphoreGive()激活信号量,使其变为 "可用" 状态。
2. 静态创建二进制信号量

c

运行

复制代码
SemaphoreHandle_t xSemaphoreCreateBinaryStatic(StaticSemaphore_t *pxStaticSemaphore);
  • 功能:使用静态内存创建二进制信号量,避免动态内存分配;
  • 参数:pxStaticSemaphore:指向静态信号量控制块的指针(需用户提前定义);
  • 返回值:
    • 非 NULL:创建成功,返回信号量句柄;
    • NULL:参数无效(如指针为 NULL);
  • 适用场景:对内存分配有严格控制的场景(如裸机移植后的资源受限环境)。
3. 获取二进制信号量(阻塞方式)

c

运行

复制代码
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);
  • 功能:尝试获取信号量,若信号量不可用则任务阻塞指定时间;
  • 参数:
    • xSemaphore:信号量句柄;
    • xTicksToWait:阻塞超时时间(单位:tick,portMAX_DELAY表示永久阻塞);
  • 返回值:
    • pdPASS:成功获取信号量;
    • pdFALSE:超时未获取到信号量;
  • 说明:获取成功后,信号量状态变为 "不可用"。
4. 释放二进制信号量

c

运行

复制代码
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
  • 功能:释放二进制信号量,使其变为 "可用" 状态,唤醒等待该信号量的最高优先级任务;
  • 参数:xSemaphore:信号量句柄;
  • 返回值:
    • pdPASS:释放成功;
    • errQUEUE_FULL:信号量已处于可用状态,释放失败;
  • 注意:仅能在任务中调用,不能在中断服务函数中使用(中断中需用xSemaphoreGiveFromISR())。
5. 中断中释放二进制信号量

c

运行

复制代码
BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken);
  • 功能:在中断服务函数中释放二进制信号量;
  • 参数:
    • xSemaphore:信号量句柄;
    • pxHigherPriorityTaskWoken:输出参数,标记是否唤醒了更高优先级任务(pdTRUE表示需要进行任务切换);
  • 返回值:
    • pdPASS:释放成功;
    • errQUEUE_FULL:信号量已可用,释放失败;
  • 说明:调用后需根据pxHigherPriorityTaskWoken的值决定是否触发任务切换(如portYIELD_FROM_ISR())。

四、计数信号量 API 函数

1. 动态创建计数信号量

c

运行

复制代码
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount);
  • 功能:创建计数信号量,支持指定最大计数和初始计数;
  • 参数:
    • uxMaxCount:信号量最大计数(超过则无法释放);
    • uxInitialCount:信号量初始计数;
  • 返回值:
    • 非 NULL:创建成功,返回句柄;
    • NULL:内存不足,创建失败;
  • 示例:创建最大计数为 5、初始计数为 0 的信号量:xSemaphoreCreateCounting(5, 0)
2. 静态创建计数信号量

c

运行

复制代码
SemaphoreHandle_t xSemaphoreCreateCountingStatic(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxStaticSemaphore);
  • 功能:使用静态内存创建计数信号量;
  • 参数:
    • uxMaxCount:最大计数;
    • uxInitialCount:初始计数;
    • pxStaticSemaphore:静态信号量控制块指针;
  • 返回值:
    • 非 NULL:创建成功;
    • NULL:参数无效;
  • 适用场景:与静态二进制信号量一致,适用于内存受限环境。
3. 获取计数信号量(阻塞方式)

c

运行

复制代码
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);
  • 功能:与二进制信号量的xSemaphoreTake()完全一致;
  • 说明:获取成功后,信号量计数减 1;若计数为 0,任务阻塞。
4. 释放计数信号量

c

运行

复制代码
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
  • 功能:释放计数信号量,计数加 1(不超过最大计数);
  • 说明:与二进制信号量的xSemaphoreGive()用法一致,仅计数逻辑不同。
5. 中断中释放计数信号量

c

运行

复制代码
BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken);
  • 功能:在中断中释放计数信号量;
  • 用法:与二进制信号量的xSemaphoreGiveFromISR()完全一致。

五、互斥信号量 API 函数

1. 动态创建互斥信号量

c

运行

复制代码
SemaphoreHandle_t xSemaphoreCreateMutex(void);
  • 功能:创建互斥信号量(初始状态为 "可用"),支持优先级继承(避免优先级翻转);
  • 返回值:
    • 非 NULL:创建成功;
    • NULL:内存不足;
  • 说明:互斥信号量与二进制信号量的核心区别是支持优先级继承,适用于共享资源互斥访问(如串口、SPI 总线)。
2. 静态创建互斥信号量

c

运行

复制代码
SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t *pxStaticSemaphore);
  • 功能:使用静态内存创建互斥信号量;
  • 参数:pxStaticSemaphore:静态互斥信号量控制块指针;
  • 返回值:
    • 非 NULL:创建成功;
    • NULL:参数无效;
3. 获取互斥信号量

c

运行

复制代码
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);
  • 功能:与二进制信号量的xSemaphoreTake()用法一致;
  • 说明:获取成功后,互斥信号量状态变为 "不可用";若被低优先级任务占用,高优先级任务会触发优先级继承(低优先级任务临时提升至高优先级)。
4. 释放互斥信号量

c

运行

复制代码
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
  • 功能:释放互斥信号量,恢复被继承的优先级(若有);
  • 注意:
    • 仅能由获取互斥信号量的任务释放,其他任务释放会失败;
    • 不能在中断中调用(互斥信号量不支持中断中操作);
  • 返回值:
    • pdPASS:释放成功;
    • errQUEUE_FULL:未获取过信号量,释放失败。

六、递归互斥信号量 API 函数

1. 动态创建递归互斥信号量

c

运行

复制代码
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void);
  • 功能:创建递归互斥信号量,允许同一任务多次获取(最多configMAX_RECURSIVE_MUTEX_CALLS次,默认 255);
  • 返回值:
    • 非 NULL:创建成功;
    • NULL:内存不足;
  • 适用场景:任务中存在嵌套访问共享资源的场景(如函数 A 调用函数 B,两者均需访问同一资源)。
2. 静态创建递归互斥信号量

c

运行

复制代码
SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic(StaticSemaphore_t *pxStaticSemaphore);
  • 功能:使用静态内存创建递归互斥信号量;
  • 参数:pxStaticSemaphore:静态递归互斥信号量控制块指针;
  • 返回值:
    • 非 NULL:创建成功;
    • NULL:参数无效。
3. 获取递归互斥信号量

c

运行

复制代码
BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);
  • 功能:获取递归互斥信号量,同一任务多次获取时计数递增;
  • 参数:与xSemaphoreTake()一致;
  • 返回值:
    • pdPASS:获取成功;
    • pdFALSE:超时失败;
  • 说明:首次获取时信号量变为 "不可用",后续同一任务获取仅递增计数。
4. 释放递归互斥信号量

c

运行

复制代码
BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xSemaphore);
  • 功能:释放递归互斥信号量,计数递减;当计数减为 0 时,信号量变为 "可用";
  • 注意:
    • 仅能由获取信号量的任务释放;
    • 释放次数需与获取次数一致,否则信号量无法完全释放;
  • 返回值:
    • pdPASS:释放成功;
    • errQUEUE_FULL:未获取过信号量或释放次数过多。

七、关键使用注意事项

  1. 信号量创建后需检查句柄是否为 NULL,避免空指针操作;
  2. 中断中仅能使用xSemaphoreGiveFromISR()释放信号量,不能使用xSemaphoreTake()xSemaphoreGive()
  3. 互斥信号量和递归互斥信号量不支持中断中操作;
  4. 计数信号量的最大计数需根据资源数量合理设置,避免溢出;
  5. 信号量使用完毕后需手动删除(动态创建),避免内存泄漏。
相关推荐
Zeku4 小时前
20251224 - 嵌入式 Linux 开发中的MQTT指南
stm32·freertos·linux驱动开发·linux应用开发
Zeku21 小时前
20251222 - 韦东山Linux开发板I.MX6ULL连接无线WiFi
stm32·freertos·linux驱动开发·linux应用开发
Zeku21 小时前
20251222 - 常用命令“source etcprofile”的详细解析
stm32·freertos·linux驱动开发·linux应用开发
Zeku1 天前
20251202 - Linux输入子系统支持的操作机制
stm32·freertos·linux驱动开发·linux应用开发
Zeku2 天前
20251202 - Linux输入子系统
stm32·freertos·嵌入式软件·linux驱动开发·linux应用开发
Zeku2 天前
20251202 - Linux输入系统的基础知识 - tslib
stm32·freertos·linux驱动开发·linux应用开发
离凌寒4 天前
一、基于freertos下对LAN8720模块进行通信测试
网络·freertos
charlie1145141918 天前
在上位机上熟悉FreeRTOS API
笔记·学习·嵌入式·c·freertos·工程
飞来客isdn9 天前
GD32F407ZGT6在FreeRTOS下串口中断接收异常情况及解决方法
单片机·mcu·freertos·信息与通信