OpenClaw系列:消息队列与邮箱——任务间通信的轻量级方案
一、一个让我熬夜到凌晨三点的bug
去年做一款工业数据采集器,主控是STM32H743,跑着FreeRTOS。三个任务:采集任务(ADC采样)、处理任务(滤波+协议封装)、发送任务(UART+Modbus)。采集任务每1ms产生一批数据,通过全局数组+标志位传给处理任务。调试时发现:偶尔出现数据错乱,比如温度值突然跳到-273°C,或者两个通道的数据互换。
用逻辑分析仪抓UART输出,发现发送任务偶尔会发出“半帧”数据——前一半是第N次采样的结果,后一半是第N+1次采样的。全局数组被覆盖了。这就是典型的生产者-消费者问题,没有互斥保护。加个互斥量?采集任务1ms一次,互斥量加锁解锁的开销在H7上虽然不大,但处理任务里还有浮点运算和滤波算法,一旦被高优先级任务抢占,互斥量持有时间过长,采集任务就会阻塞——这会导致采样间隔抖动,对工业现场来说就是灾难。
后来换成消息队列,问题彻底解决。今天就把消息队列和邮箱这两个轻量级通信方案掰开揉碎讲清楚。
二、消息队列:不只是“先进先出”那么简单
2.1 本质是个环形缓冲区+任务阻塞机制
消息队列在RTOS内核里,本质上就是一个环形缓冲区,外加一个等待队列。发送任务往队列里写数据,接收任务从队列里读数据。关键区别在于:当队列满时,发送任务可以选择阻塞等待;当队列空时,接收任务也可以阻塞等待。
看FreeRTOS的队列创建函数: