当前位置: 首页 > news >正文

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.xdnf.cn/news/620245.html

相关文章:

  • .NET ORM开发手册:基于SqlSugar的高效数据访问全攻略
  • LangChain构建RAG的对话应用
  • Windows 11 电源计划进阶——通过异类策略优化大小核CPU调度
  • 机器学习的一些基本概念
  • DNS Server在高可用高并发系统中的应用
  • 基于cornerstone3D的dicom影像浏览器 第二十二章 mpr + vr
  • 如何选择支持AI接入的开发语言与框架
  • 错误原因详解
  • windows10重装ssh无法下载
  • List<Integer> list=new ArrayList<>()
  • SpringAI 大模型应用开发篇-纯 Prompt 开发(舔狗模拟器)、Function Calling(智能客服)、RAG (知识库 ChatPDF)
  • 万亿参数背后的算力密码:大模型训练的分布式架构与自动化运维全解析
  • 开源与闭源之争:AI时代的创新博弈与未来抉择
  • 记录将网站从http升级https
  • 【前端系列】ECharts:数据可视化的强大工具
  • 打卡第27天:函数的定义与参数
  • 通过shell脚本检测服务是否存活并进行邮件的通知
  • JavaSE核心知识点03高级特性03-02(多线程)
  • C++构造和折构函数详解,超详细!
  • NC IntellisysIQ QP、QPA和QPD QP3 Slave buried slave ON RS232 等通讯接口针脚定义
  • LoRA(Low-Rank Adaptation)
  • ISO 26262-5 评估硬件架构度量值
  • 文章记单词 | 第108篇(六级)
  • 单目视觉测量及双目视觉测量
  • 【GPU并行计算】不同设备上的GPU性能分析
  • 使用arXiv.org上的资源进行学术研究
  • 【agent】一个智能助手agent
  • PCIe学习笔记(3)链路初始化和训练
  • TCP为什么是三次握手,而不是二次?
  • JavaScript 语句标识符详解