30-消息队列

一、消息队列概述

        队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、 中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列里面读取消息,当队列中的消息是空时,读取消息的任务将被阻塞,用户还可以指定阻塞的任务时间 xTicksToWait,在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。

        当队列中有新消息时,被阻塞的任务会被唤醒并处理新消息;当等待的时间超过了指定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转为就绪态。

        消息队列是一种异步的通信方式。通过消息队列服务,任务或中断服务例程可以将一条或多条消息放入消息队列中。同样,一个或多个任务可以从消息队列中获得消息。当有多个消息发送到消息队列时,通常是将先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入消息队列的 消息,即先进先出原则(FIFO),但是也支持后进先出原则(LIFO)。

特性
FreeRTOS 中使用队列数据结构实现任务异步通信工作,具有如下特性:
  • 消息支持先进先出方式排队,支持异步读写工作方式。
  • 读写队列均支持超时机制。
  • 消息支持后进先出方式排队,往队首发送消息(LIFO)。
  • 可以允许不同长度(不超过队列节点最大值)的任意类型消息。
  • 一个任务能够从任意一个消息队列接收和发送消息。
  • 多个任务能够从同一个消息队列接收和发送消息。
  • 当队列使用结束后,可以通过删除队列函数进行删除。

二、常用函数接口


//头文件
#include "queue.h"

1.消息队列创建函数

 QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength,UBaseType_t uxItemSize);功能描述:用于创建一个新的队列。
参数:
- uxQueueLength-队列能够存储的最大消息单元数目,即队列长度。
- uxItemSize-队列中消息单元的大小,以字节为单位,该大小设置非常重要,否则得到的数据不完整。返回值:
成功-如果创建成功则返回一个队列句柄,用于访问创建的队列;
失败-如果创建不成功则返回NULL,可能原因是创建队列需要的 RAM 无法分配成功。eg:
//创建消息队列,Q_LEN为4,Q_SIZE为32
g_queue = xQueueCreate(Q_LEN, Q_SIZE);

2.消息队列静态创建函数

QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,UBaseType_t uxItemSize,uint8_t *pucQueueStorageBuffer,StaticQueue_t *pxQueueBuffer );功能描述:用于创建一个新的队列。
参数:
- uxQueueLength-队列能够存储的最大消息单元数目,即队列长度。
- uxItemSize-队列中消息单元的大小,以字节为单位。
- pucQueueStorageBuffer-指针,指向一个 uint8_t 类型的数组,数组的大小至少有uxQueueLength* uxItemSize 个字节。当 uxItemSize 为 0 时,pucQueueStorageBuffer 可以为 NULL。
- pxQueueBuffer-指针,指向 StaticQueue_t 类型的变量,该变量用于存储队列的数据结构。
返回值:
成功-如果创建成功则返回一个队列句柄,用于访问创建的队列;
失败-如果创建不成功则返回NULL,可能原因是创建队列需要的 RAM 无法分配成功。

3.用于向队列尾部发送一个队列消息

BaseType_t xQueueSend(QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait);参数说明:
- xQueue-队列句柄。
- pvItemToQueue-指针,指向要发送到队列尾部的队列消息。
- xTicksToWait-队列满时,等待队列空闲的最大超时时间。
如果队列满并且xTicksToWait 被设置成 0,函数立刻返回。超时时间的单位为系统节拍周期,
常量 portTICK_PERIOD_MS 用于辅助计算真实的时间,单位为 ms。
如果 INCLUDE_vTaskSuspend 设置成 1,并且指定延时为 portMAX_DELAY 将导致任务挂起(没有超时)。返回值:
消息发送成功成功返回 pdTRUE,否则返回 errQUEUE_FULL。eg:
//往消息队列中发送消息
xReturn = xQueueSend(g_queue, send_buff, portMAX_DELAY );
if(xReturn != pdTRUE)
{printf("send failure\r\n");
}

4.在中断服务程序中用于向队列尾部发送一个消息

BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);参数说明:
- xQueue-队列句柄。
- pvItemToQueue-指针,指向要发送到队列尾部的消息。
- pxHigherPriorityTaskWoken-如果入队导致一个任务解锁,
并且解锁的任务优先级高于当前被中断的任务,
则将*pxHigherPriorityTaskWoken设置成 pdTRUE,
然后在中断退出前需要进行一次上下文切换,去执行被唤醒的优先级更高的任务,
可提高实时性。从FreeRTOS V7.3.0 起,
pxHigherPriorityTaskWoken 作为一个可选参数,可以设置为 NULL。返回值:
消息发送成功成功返回 pdTRUE,否则返回 errQUEUE_FULL。

5.向队列队首发送一个消息

BaseType_t xQueueSendToFront( QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait );参数说明:
- xQueue-队列句柄。
- pvItemToQueue-指针,指向要发送到队列尾部的消息。
- xTicksToWait-队列满时,等待队列空闲的最大超时时间。
如果队列满并且xTicksToWait 被设置成 0,函数立刻返回。
超时时间的单位为系统节拍周期,常量 portTICK_PERIOD_MS 用于辅助计算真实的时间,
单位为 ms。如果 INCLUDE_vTaskSuspend 设置成 1,
并且指定延时为 portMAX_DELAY 将导致任务无限阻塞(没有超时)。返回值:
消息发送成功成功返回 pdTRUE,否则返回 errQUEUE_FULL。

6.在中断服务程序中向消息队列队首发送一个消息

BaseType_t xQueueSendToFrontFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);参数说明:
- xQueue-队列句柄。
- pvItemToQueue-指针,指向要发送到队首的消息。
- pxHigherPriorityTaskWoken-如果入队导致一个任务解锁,
并且解锁的任务优先级高于当前被中断的任务,
则将*pxHigherPriorityTaskWoken设置成 pdTRUE,
然后在中断退出前需要进行一次上下文切换,去执行被唤醒的优先级更高的任务。
从FreeRTOS V7.3.0 起,pxHigherPriorityTaskWoken 作为一个可选参数,可以设置为 NULL。返回值:
消息发送成功成功返回 pdTRUE,否则返回 errQUEUE_FULL。

7.从一个队列中接收消息,并把接收的消息从队列中删除

BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);参数说明:
- xQueue-队列句柄。
- pvBuffer-指针,指向接收到要保存的数据。
- xTicksToWait-队列空时,阻塞超时的最大时间。如果该参数设置为 0,
函数立刻返回。超时时间的单位为系统节拍周期,
常量 portTICK_PERIOD_MS 用 于辅助计算真实的时间,单位为 ms。
如果 INCLUDE_vTaskSuspend 设 置成 1,并且指定延时为 portMAX_DELAY 
将导致任务无限阻塞(没有超时)。返回值:
队列项接收成功返回 pdTRUE,否则返回 pdFALSE。若接收完消息,不想删除,可以使用xQueuePeek函数。eg:
//阻塞等待消息
xReturn = xQueueReceive(g_queue, recv_buff, portMAX_DELAY);
if(xReturn != pdTRUE)
{printf("send failure\r\n");
}//记得给缓冲区清零
memset(recv_buff, 0, sizeof (recv_buff));

8.在中断中从一个队列中接收消息,并从队列中删除该消息

BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken);参数说明:
- xQueue-队列句柄。
- pvBuffer-pxHigherPriorityTaskWoken
- pxHigherPriorityTaskWoken-在使用之前必须初始化成 pdFALSE。
如果API函数(即xQueueReceiveFromISR)导致一个任务解锁,
并且解锁的任务优先级高于当前运行的任务,则API函数(即xQueueReceiveFromISR)将*pxHigherPriorityTaskWoken设置成pdTRUE。在中断退出前,触发一次任务切换。pxHigherPriorityTaskWoken 作为一个可选参数,可以设置为NULL。返回值:
队列项接收成功返回 pdTRUE,否则返回 pdFALSE。
若接收完消息,不想删除,可以使用xQueuePeekFromISR函数。

三、示例代码

1、任务与任务之间的源码

https://download.csdn.net/download/m0_63622771/90897081

2、任务与中断之间的源码

https://download.csdn.net/download/m0_63622771/90897085

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82280.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI Agent开发第74课-解构AI伪需求的魔幻现实主义

开篇 🚀在之前的系列中我们狂炫了AI Agent的各种高端操作(向量数据库联动、多模态感知、动态工作流等…),仿佛每个程序员都能用LLM魔法点石成金✨。 但今天咱们要泼一盆透心凉的冷水——当企业把AI当成万能胶水强行粘合所有需求时,连电风扇都能被玩出量子纠缠的魔幻现实…

低代码AI开发新趋势:Dify平台化开发实战

在人工智能快速发展的今天,AI应用的开发方式也在不断演变。从传统的手写代码到如今的低代码甚至零代码开发,技术的进步让更多的非专业开发者也能轻松上手。本文将带你走进Dify平台化开发的世界,探索如何通过这一强大的低代码AI开发平台&#…

开发积累总结

export default 和export const 均用于从模块导出函数、对象或原始值,区别在于: export default:一个文件中只能有一个,为默认导出,在引用时指定名字。 export const:一个文件中有多个,为命名…

【TCP/IP协议族详解】

目录 第1层 链路/网络接口层—帧(Frame) 1. 链路层功能 2. 常见协议 2.1. ARP(地址解析协议) 3. 常见设备 第2层 网络层—数据包(Packet) 1. 网络层功能 2. 常见协议 2.1. ICMP(互联网…

vocabulary in program

编号意思(英译中)音标单词1n. 稀薄;稀罕;珍奇/ˈreərɪsn/rareness2n.登记表,注册簿;注册员;(人或乐器的)声区,音区;(适合特定场合使…

整平机技术进阶:从原理到实战的深度解析

一、整平机的力学原理与数学模型 整平机的核心在于通过材料塑性变形消除内应力,其力学过程可简化为以下模型: 弹塑性变形理论 当材料通过辊轮时,表层受拉应力,芯部受压应力,超过屈服强度后产生永久变形。 关键公式&a…

【b站计算机拓荒者】【2025】微信小程序开发教程 - chapter1 初识小程序 - 3项目目录结构4快速上手

3 项目目录结构 3.1 项目目录结构 3.1.1 目录介绍 # 1 项目主配置文件,在项目根路径下,控制整个项目的-app.js # 小程序入口文件,小程序启动,会执行此js-app.json # 小程序全局配置文件,配置小程序导航栏颜色等信息…

427. 建立四叉树

https://leetcode.cn/problems/construct-quad-tree/description/?envTypestudy-plan-v2&envIdtop-interview-150思路:这题乍一看很复杂但是只要读懂题找到规律就会发现其实很简单 四叉树的构造规律: 1. 如果一个区域的值全相等,那么这个…

IDEA中创建SpringBoot项目没有Java8

IDEA中创建SpringBoot项目没有Java8 文章目录 IDEA中创建SpringBoot项目没有Java8一:解决办法 很久没单独创建springboot项目,今天使用idea的Spring Initializr 创建 Spring Boot项目时,发现java版本里,无法选择jdk1.8,只有17、21、22,所以本文介绍了使用Spring Ini…

聊一聊手动测试与探索性测试的区别

目录 一 定义与目标 手动测试 探索性测试 二 执行方式 手动测试 探索性测试 三 测试重点及计划性 手动测试 探索性测试 四 测试效率及成本 手动测试 探索性测试 五 优缺点对比 六 关键却别与总结 七 适应场景 手动测试 探索性测试 八 实际应用与结合 在我们进…

Spring用到的设计模式

Spring框架中广泛应用了多种设计模式,以提升代码的灵活性和可维护性。 工厂模式:BeanFactory,整个 IoC 容器就是一个工厂。 单例模式:Spring 管理的 Bean 默认都是单例的。 模版方法:如 RedisTemplate、JdbcTemplat…

Mybatis(2)

sql注入攻击 SQL注入攻击是一种常见的网络安全威胁,攻击者通过在输入字段中插入恶意SQL代码,绕过应用程序的安全机制,直接操纵数据库。 SQL注入的原理 SQL注入利用应用程序未对用户输入进行充分过滤或转义的漏洞。当用户输入被直接拼接到S…

【Node.js】高级主题

个人主页:Guiat 归属专栏:node.js 文章目录 1. Node.js 高级主题概览1.1 高级主题架构图 2. 事件循环与异步编程深度解析2.1 事件循环机制详解事件循环阶段详解 2.2 异步编程模式演进高级异步模式实现 3. 内存管理与性能优化3.1 V8 内存管理机制内存监控…

冰箱热交换的原理以及如何加氟

冰箱如何加氟: 氟利昂被节流装置降压后,进入冰箱的蒸发器,此时它处于低温低压液态状态。在冰箱内部(例如 0C 或 -10C):它很容易气化(因为其沸点很低)在气化过程中吸收周围热量。 1…

WordPress多语言插件安装与使用教程

WordPress多语言插件GTranslate的使用方法 在wordpress网站后台搜索多语言插件GTranslate并安装,安装完成、用户插件后开始设置,以下为设置方法: 1、先在后台左侧找到Gtranslate,进入到设置界面 2、选择要显示的形式&#xff0c…

DELL EMC PowerStore BBU更换手册

写在前面 上周给客户卖了一个BBU电池,客户要写一个更换方案。顺利完成了更换,下面就把这个更换方案给大家share出来,以后客户要写,您就Ctrlc 和Ctrlv就可以了。 下面的步骤是最理想的方式,中间没有任何的问题&#xff…

FastMCP:为大语言模型构建强大的上下文和工具服务

FastMCP:为大语言模型构建强大的上下文和工具服务 在人工智能快速发展的今天,大语言模型(LLM)已经成为许多应用的核心。然而,如何让这些模型更好地与外部世界交互,获取实时信息,执行特定任务&a…

CMake基础:CMakeLists.txt 文件结构和语法

目录 1.CMakeLists.txt基本结构 2.核心语法规则 3.关键命令详解 4.常用预定义变量 5.变量和缓存 6.变量作用域与传递 7.注意事项 1.CMakeLists.txt基本结构 CMakeLists.txt 是 CMake 构建系统的核心配置文件,采用命令式语法组织项目结构和编译流程。主要用于…

战略-2.1 -战略分析(PEST/五力模型/成功关键因素)

战略分析路径,先宏观(PEST)、再产业(产品生命周期、五力模型、成功关键因素)、再竞争对手分析、最后企业内部分析。 本文介绍:PEST、产品生命周期、五力模型、成功关键因素、产业内的战略群组 一、宏观环境…

深入理解设计模式:工厂模式、单例模式

深入理解设计模式:工厂模式、单例模式 设计模式是软件开发中解决常见问题的可复用方案。本文将详细介绍两种种重要的创建型设计模式:工厂模式、单例模式,并提供Java实现示例。 一、工厂模式 工厂模式是一种创建对象的设计模式,…