news 2026/5/1 18:14:23

FreeRTOS队列:入队与出队详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FreeRTOS队列:入队与出队详解

一、基本概念

入队(Enqueue):向队列中添加数据(发送消息)出队(Dequeue):从队列中获取数据(接收消息)

FreeRTOS队列采用FIFO(先进先出)机制,是任务间通信的核心方式。队列存储的是数据的拷贝,而非指针,确保了数据安全。

二、队列数据结构

队列的核心结构体Queue_t包含以下关键成员:

typedef struct QueueDefinition { int8_t *pcHead; // 指向队列存储区开始地址 int8_t *pcWriteTo; // 指向存储区中下一个空闲位置 union { QueuePointers_t xQueue; // 队列相关数据 SemaphoreData_t xSemaphore; // 信号量相关数据 } u; List_t xTasksWaitingToSend; // 等待发送任务列表(按优先级排序) List_t xTasksWaitingToReceive; // 等待接收任务列表(按优先级排序) volatile UBaseType_t uxMessagesWaiting; // 当前队列中消息数量 UBaseType_t uxLength; // 队列长度(最大可存储消息数) UBaseType_t uxItemSize; // 每个消息的大小 volatile int8_t cRxLock; // 接收锁 } Queue_t;

队列空/满判断

  • 队列为空pcWriteTo == pcReadFrom
  • 队列已满pcWriteTo + itemSize == pcReadFrom(考虑回绕)

三、入队操作

1. 入队函数

// 向队列尾部入队(默认方式) BaseType_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait); // 向队列头部入队 BaseType_t xQueueSendToFront(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait); // 覆写入队(仅当队列长度为1时有效) BaseType_t xQueueOverwrite(QueueHandle_t xQueue, const void *pvItemToQueue);

2. 入队操作原理

  1. 检查队列状态

    • 如果队列未满,继续入队
    • 如果队列已满,根据等待时间决定处理方式
  2. 数据拷贝

    • 调用prvCopyDataToQueue将数据从源地址拷贝到队列存储区
    • uxMessagesWaiting(消息数量)+1
  3. 任务唤醒

    • 如果有任务在等待接收(xTasksWaitingToReceive非空)
    • 将等待接收任务从阻塞态唤醒,加入就绪队列
    • 调用vTaskMissedYield()进行任务切换
  4. 队列满处理

    • 如果等待时间不为0,将当前任务加入等待发送列表
    • 如果等待时间=0,直接返回errQUEUE_FULL

3. 入队阻塞机制

阻塞时间行为
0立即返回,不等待
0 ~ portMAX_DELAY等待指定时间,超时后返回
portMAX_DELAY无限等待,直到队列有空闲位置

四、出队操作

1. 出队函数

// 从队列接收数据(出队并删除数据) BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); // 从队列读取数据(出队但不删除数据) BaseType_t xQueuePeek(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);

2. 出队操作原理

  1. 检查队列状态

    • 如果队列非空,继续出队
    • 如果队列为空,根据等待时间决定处理方式
  2. 数据拷贝

    • 将队列中的数据拷贝到接收缓冲区
    • uxMessagesWaiting(消息数量)-1
  3. 任务唤醒

    • 如果有任务在等待发送(xTasksWaitingToSend非空)
    • 将等待发送任务从阻塞态唤醒,加入就绪队列
    • 调用vTaskMissedYield()进行任务切换
  4. 队列空处理

    • 如果等待时间不为0,将当前任务加入等待接收列表
    • 如果等待时间=0,直接返回errQUEUE_EMPTY

3. 出队阻塞机制

阻塞时间行为
0立即返回,不等待
0 ~ portMAX_DELAY等待指定时间,超时后返回
portMAX_DELAY无限等待,直到队列有消息

五、入队与出队的对比

特性入队出队
数据传递方式值传递(拷贝数据)值传递(拷贝数据)
队列满处理阻塞等待或返回错误队列满不影响入队
队列空处理队列空不影响出队阻塞等待或返回错误
阻塞优先级优先级最高的任务先被唤醒优先级最高的任务先被唤醒
消息顺序FIFO(先进先出)FIFO(先进先出)

六、实际使用示例

入队示例(发送消息)

// 创建队列 QueueHandle_t xQueue = xQueueCreate(5, sizeof(uint32_t)); // 任务中发送消息 void SenderTask(void *pvParameters) { uint32_t data = 0; while(1) { data++; // 向队列尾部发送数据,阻塞等待10个tick if(xQueueSendToBack(xQueue, &data, 10) != pdPASS) { // 队列满,处理错误 } } }

出队示例(接收消息)

// 任务中接收消息 void ReceiverTask(void *pvParameters) { uint32_t data; while(1) { // 从队列头部接收数据,永久阻塞 if(xQueueReceive(xQueue, &data, portMAX_DELAY) == pdPASS) { // 处理接收到的数据 } } }

七、关键注意事项

  1. 数据拷贝:队列存储的是数据的拷贝,不是指针。传递大结构体时,建议使用指针传递(传递结构体地址),但需确保指针指向的数据在队列处理期间有效。

  2. 队列长度:合理设置队列长度,过小会导致频繁阻塞,过大则浪费内存。

  3. 阻塞时间:根据应用需求设置合适的阻塞时间,避免任务长时间阻塞。

  4. 中断安全:在中断中操作队列,必须使用xQueueSendFromISRxQueueReceiveFromISR

  5. 队列空/满检测:使用uxQueueMessagesWaiting()uxQueueSpacesAvailable()查询队列状态,避免数据丢失。

八、队列工作流程图

任务A(发送) 队列 任务B(接收) | | | | 入队操作 | | |----------------->| | | | | | | | | | 入队成功 | | |--------------->| | | | | | | | | | | | 出队操作 | | |<---------------| | | | | | |

入队和出队操作确保了任务间的解耦,使系统设计更加清晰、灵活,是FreeRTOS中实现任务间通信的关键机制。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 16:21:41

百考通AI数据分析助手,一键生成专业报告!

在数据驱动的时代&#xff0c;海量信息既是宝藏&#xff0c;也是负担。对于企业高管、市场分析师、科研人员乃至学生而言&#xff0c;如何从纷繁复杂的数据中提炼价值、洞察趋势、支撑决策&#xff0c;已成为一项核心竞争力。然而&#xff0c;面对堆积如山的Excel表格和CSV文件…

作者头像 李华
网站建设 2026/4/25 10:11:54

GitCode项目链接收藏:第一时间获取VibeThinker更新动态

VibeThinker-1.5B&#xff1a;小模型如何实现高精度数学与编程推理&#xff1f; 在当前大模型“军备竞赛”愈演愈烈的背景下&#xff0c;动辄千亿参数、百万美元训练成本的AI系统已屡见不鲜。然而&#xff0c;在真实应用场景中&#xff0c;我们真的需要如此庞大的模型吗&#x…

作者头像 李华
网站建设 2026/4/26 13:15:45

系统维护必备:Driver Store Explorer驱动清理详解

驱动臃肿&#xff1f;系统变慢&#xff1f;一招清理Windows“隐形垃圾”——Driver Store Explorer实战指南你有没有遇到过这种情况&#xff1a;一台刚重装不久的电脑&#xff0c;C盘空间却莫名其妙少了几个GB&#xff1f;或者在部署虚拟机模板时&#xff0c;发现克隆速度越来越…

作者头像 李华
网站建设 2026/4/25 11:19:51

【抢占AI内容先机】:Dify描述生成性能提升的5个黄金法则

第一章&#xff1a;Dify描述生成性能优化的底层逻辑在构建基于大语言模型&#xff08;LLM&#xff09;的应用时&#xff0c;Dify作为低代码平台&#xff0c;其描述生成性能直接影响用户体验与系统吞吐。性能优化并非仅依赖模型本身&#xff0c;而是由请求调度、缓存策略、上下文…

作者头像 李华