--- type: concept title: FreeRTOS 任务间通信(IPC) tags: [freertos, rtos, queue, semaphore, mutex, event-group, task-notification, ipc, concept] created: 2026-07-12 --- # FreeRTOS 任务间通信(IPC) ## 消息队列 队列是任务间通信的主要形式,可在任务之间以及中断和任务之间发送消息。 - **FIFO 顺序**:先发送先接收 - **线程安全**:操作原子性 - **阻塞/非阻塞**:满/空时可等待或立即返回 - **可变长度项** ### 队列 API | 函数 | 描述 | |------|------| | `xQueueCreate()` | 动态创建队列 | | `xQueueSend()` / `xQueueSendToBack()` | 尾部写入 | | `xQueueSendToFront()` | 头部写入 | | `xQueueOverwrite()` | 覆写(队列长度=1) | | `xQueueReceive()` | 头部读取并删除 | | `xQueuePeek()` | 头部读取不删除 | ### 队列集(Queue Set) 管理多个队列和信号量的数据结构。通过单一 API 调用操作一组相关队列。 | API 函数 | 描述 | |----------|------| | `xQueueCreateSet()` | 创建队列集 | | `xQueueAddToSet()` | 添加队列到队列集 | | `xQueueSelectFromSet()` | 获取有消息的队列成员 | ## 信号量 | 类型 | 用途 | |------|------| | **二值信号量** | 互斥访问 / 任务同步(类似长度为 1 的队列) | | **计数信号量** | 事件计数 / 资源管理(类似长度 >1 的队列) | | **互斥信号量** | 带优先级继承的互斥(解决优先级翻转) | ### 二值信号量 ```c SemaphoreHandle_t xSemaphoreCreateBinary(void); xSemaphoreGive(sem); // 释放 xSemaphoreTake(sem); // 获取 ``` ### 计数信号量 ```c SemaphoreHandle_t xSemaphoreCreateCounting(max, initial); uxSemaphoreGetCount(sem); ``` ### 互斥信号量与优先级翻转 **优先级翻转**:低优先级任务持有资源时被中优先级任务抢占,导致高优先级任务被阻塞等待,违反实时性。 ![Priority inversion](../raw/FreeRTOS/尚硅谷FreeRTOS教程/assets/freertos_priority_inversion.png) **互斥信号量**包含优先级继承机制:当高优先级任务等待低优先级任务持有的资源时,系统临时提升低优先级任务的优先级,将影响降至最低。 ![Mutex priority inheritance](../raw/FreeRTOS/尚硅谷FreeRTOS教程/assets/freertos_mutex_priority_inheritance.png) **注意**:互斥信号量不能在中断中使用(优先级继承机制需从任务上下文中调用)。 ## 事件标志组 轻量级机制,每个标志位代表特定状态或事件。 ![Event group bits](../raw/FreeRTOS/尚硅谷FreeRTOS教程/assets/freertos_event_group_bits.png) | API 函数 | 描述 | |----------|------| | `xEventGroupCreate()` | 创建事件标志组 | | `xEventGroupSetBits()` | 设置标志位 | | `xEventGroupClearBits()` | 清零标志位 | | `xEventGroupWaitBits()` | 等待标志位(可等待多个位同时置 1) | | `xEventGroupSync()` | 设置位并等待 | **与信号量的区别**:事件标志组侧重事件通知(多个位),信号量侧重资源控制(计数器)。 ## 任务通知 每个 RTOS 任务都有一个 32 位通知值,可替代二值信号量或事件标志组,是更轻量的通信方式(无需中间对象)。 ![Task notification direct vs indirect](../raw/FreeRTOS/尚硅谷FreeRTOS教程/assets/freertos_task_notification_direct.png) ![Task notification vs indirect](../raw/FreeRTOS/尚硅谷FreeRTOS教程/assets/freertos_task_notification_vs_indirect.png) ### 任务通知 API | API 函数 | 描述 | |----------|------| | `xTaskNotify()` | 发送通知带通知值 | | `xTaskNotifyGive()` | 发送通知不带通知值 | | `ulTaskNotifyTake()` | 获取通知(清零或减 1) | | `xTaskNotifyWait()` | 获取通知可读取通知值 | **注意**:发送通知有 FromISR 版本,接收通知无 ISR 版本。 ### 任务通知的三种典型用法 1. **模拟二值信号量**:`xTaskNotifyGive()` + `ulTaskNotifyTake(pdTRUE, portMAX_DELAY)` 2. **模拟消息邮箱**:`xTaskNotify(handle, value, eSetValueWithOverwrite)` + `xTaskNotifyWait()` 3. **模拟事件标志组**:`xTaskNotify(handle, EVENTBIT, eSetBits)` + `xTaskNotifyWait()` ## 相关页面 - [[source-freertos|尚硅谷 FreeRTOS 教程 - 资料页]] - [[freertos-interrupt-time|中断管理与时间管理]] - [[freertos-system-services|系统服务(定时器、低功耗、内存)]]