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

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.lryc.cn/news/2385363.html

相关文章:

  • 跨域解决方案之JSONP
  • 【AI测试革命】第七期:AI性能测试的深度实践——从智能建模到自动化调优的全链路升级
  • Thinkphp6使用token+Validate验证防止表单重复提交
  • AppAgentx 开源AI手机操控使用分享
  • Axure设计之带分页的穿梭框原型
  • 嵌入式硬件篇---陀螺仪|PID
  • 电机控制储备知识学习(五) 三项直流无刷电机(BLDC)学习(四)
  • Java—— 网络爬虫
  • Baklib内容中台的主要构成是什么?
  • 深度解析 Java 中介者模式:重构复杂交互场景的优雅方案
  • 家用和类似用途电器的安全 第1部分:通用要求 与2005版差异(7)
  • HTTP Digest 认证:原理剖析与服务端实现详解
  • untiy实现汽车漫游
  • PID项目---硬件设计
  • Pluto实验报告——基于FM的音频信号传输并解调恢复
  • 【Redis】AOF日志
  • Leetcode 2792. 计算足够大的节点数
  • 《关于浔川社团退出DevPress社区及内容撤回的声明》
  • Windows逆向工程提升之IMAGE_RESOURCE_DIRECTORY
  • 使用ps为图片添加水印
  • x64_ubuntu22.04.5安装:cuda driver + cuda toolkit
  • 开盘啦 APP 抓包 逆向分析
  • vs2022 Qt Visual Studio Tools插件设置
  • Python包__init__.py标识文件解析
  • 【MySQL】第8节|Innodb底层原理与Mysql日志机制深入剖析(一)
  • 电商ERP管理系统,Java+Vue,含源码与文档,统筹订单、库存等,助力电商企业高效运营
  • Spring Boot微服务架构(四):微服务的划分原则
  • 【打卡】树状数组的操作
  • OpenLayers 加载动画控件
  • Oracle 基础知识作业的使用