在RT-Thread中,消息队列适用于频繁产生数据但处理时间较长的应用场景,例如:传感器采样、任务通知。
消息池(pool):固定数量的消息块组成的循环缓冲区,用来存放具体消息内容。
链表1 - 空闲消息块链表:
链表2 - 已用消息块链表:
简化示意:
[ 空闲消息块链表 ] ← 发送 → [ 已用消息块链表 ] ← 接收
rt_mq_t mq = rt_mq_create("mq1", // 名称
32, // 每条消息32字节
10, // 最多10条消息
RT_IPC_FLAG_FIFO); // 先进先出调度
char data[32] = "hello";
rt_mq_send(mq, data, sizeof(data));
data
复制到空块中。关于"76次直接写入"
在发送消息时,RT-Thread内部会最多尝试76次寻找空闲消息块:
-RT_EFULL
。小总结:
项目 | 描述 |
---|---|
76次扫描 | 最多循环76次找空闲消息块 |
成功情况 | 立即找到空块,不需要76次 |
队列满了 | 76次后认定失败,返回错误 |
为什么是76 | 折中考虑(效率+资源) |
char recv_buf[32];
rt_mq_recv(mq, recv_buf, sizeof(recv_buf), RT_WAITING_FOREVER);
recv_buf
中。rt_mq_delete(mq);
【发送时】
空闲链表取块 → 写数据 → 加入已用链表
【接收时】
已用链表取块 → 读数据 → 放回空闲链表
发送消息:
接收消息:
发送线程或接收线程休眠时
├── 检查是否设置超时
│ ├── 是:启动定时器
│ └── 否:一直等待
├── 有资源可用时被唤醒(正常)
└── 超时定时器到期被唤醒(异常)
发送线程(带超时保护)
void sender_thread(void *parameter)
{
char msg[] = "sensor data";
while (1)
{
if (rt_mq_send_wait(mq, msg, sizeof(msg), 200) != RT_EOK)
{
rt_kprintf("Send timeout or error!\n");
}
rt_thread_mdelay(500);
}
}
接收线程(带超时保护)
void receiver_thread(void *parameter)
{
char buffer[32];
while (1)
{
if (rt_mq_recv(mq, buffer, sizeof(buffer), 100) == RT_EOK)
{
rt_kprintf("Received: %s\n", buffer);
}
else
{
rt_kprintf("Receive timeout!\n");
}
}
}
RT-Thread的消息队列机制高效而简洁,非常适合需要轻量化、高实时通信的场合。