FIFO顺序缓存
消息队列采用先进先出机制,确保消息按照发送顺序被消费。 队列内部维护读写指针,实现高效的消息缓存和检索。
消息队列用于实现任务间FIFO顺序通信,支持多消息缓存与异步解耦, 是高频事件与数据流传输的核心机制之一。
消息队列是任务间通信的核心机制
消息队列(Message Queue)是一种基于FIFO(先进先出)的通信机制, 允许任务之间通过队列缓冲区进行异步数据传输。 生产者任务将消息发送到队列尾部,消费者任务从队列头部按顺序接收消息, 从而实现任务解耦和数据顺序一致性。
消息队列采用先进先出机制,确保消息按照发送顺序被消费。 队列内部维护读写指针,实现高效的消息缓存和检索。
生产者和消费者运行节奏独立,无需同步等待。 生产者可连续发送消息,消费者按需接收,提高系统吞吐能力。
与事件标志不同,消息队列可携带实际数据内容。 支持传输传感器读数、通信帧数据、状态信息等结构化数据。
队列可缓存多条消息,适应高频事件场景。 当生产者速度快于消费者时,队列起到缓冲作用,避免数据丢失。
HRTOS 如何实现消息队列通信
在 HRTOS 中,消息队列的实现围绕队列初始化、消息发送、消息接收和队列管理四个核心环节展开。 每个环节都经过精心设计,确保通信的高效性和可靠性。
初始化内容:分配队列缓冲区、设置队列容量、初始化读写指针
缓冲管理:使用静态数组作为消息存储空间
参数配置:指定队列大小和消息数据类型
状态设置:队列初始状态为空,等待消息写入
发送方式:将消息写入队列尾部,更新写指针
队列检查:检测队列是否已满,满时返回失败
数据拷贝:将消息数据拷贝到队列缓冲区
任务唤醒:如有等待接收的任务,唤醒其运行
接收方式:从队列头部读取消息,更新读指针
队列检查:检测队列是否为空,空时可阻塞等待
数据读取:从队列缓冲区拷贝消息数据到接收缓冲区
阻塞机制:支持非阻塞和阻塞两种接收模式
指针管理:维护读指针和写指针,实现循环队列
状态跟踪:记录队列当前消息数量
溢出保护:防止队列溢出和数据覆盖
任务同步:管理等待发送和接收的任务列表
消息从发送到接收的完整执行路径
消息队列通信的完整实现
producer 任务函数,持续发送消息到队列
#include "hrtos.h"
static os_msgq_t g_msgq;
static u8 g_msgq_buf[16];
sbit LED_P = P1^0;
sbit LED_C = P1^1;
sbit LED_Q = P1^2;
/* Producer */
void producer(void)
{
u8 data = 0x10;
while(1)
{
os_msgq_send(&g_msgq, 0, data, 0);
LED_P = ~LED_P;
LED_Q = 1; // queue active
data++;
os_delay(3);
}
}
consumer 任务函数,从队列接收并处理消息
/* Consumer */
void consumer(void)
{
u8 data;
while(1)
{
if(os_msgq_recv(&g_msgq, 0, &data, 0))
{
LED_C = ~LED_C;
P1 = (P1 & 0xF0) | (data & 0x0F);
LED_Q = 0;
}
os_delay(2);
}
}
hrtos_main 函数,初始化队列并创建生产者和消费者任务
void hrtos_main(void)
{
os_msgq_init(&g_msgq, g_msgq_buf, sizeof(g_msgq_buf));
os_task_create((unsigned int)producer, 1, 3, 5);
os_task_create((unsigned int)consumer, 2, 2, 5);
}
示例执行后的预期行为
使用本示例时需要关注的关键点
g_msgq_buf 数组大小决定了队列容量,容量不足会导致消息发送失败。 本示例使用 16 字节缓冲区,实际应用中应根据消息频率和数据大小调整。
producer 优先级为 3,consumer 优先级为 2。 较低的消费者优先级确保队列不会因消费过快而空,体现缓冲作用。
本示例使用非阻塞模式(超时参数为 0)。 实际应用中可根据需求设置超时时间,实现阻塞等待机制。
当生产者速度快于消费者时,队列可能满。 需要合理设计队列容量和任务调度策略,避免消息丢失。
深入学习的相关资源