OpenClaw系列026:信号量与互斥锁——多任务同步与资源保护
一次血泪教训:串口打印乱码引发的三天排查
去年做一款工业数据采集器,主控是STM32H743,跑FreeRTOS。三个任务:传感器采集、数据处理、LCD显示。数据通过环形缓冲区传递,一切看起来完美。直到量产前,现场反馈设备运行几小时后,LCD显示的数据偶尔出现“跳变”——某个传感器值突然变成0,然后又恢复。
我第一反应是传感器故障。但抓了串口日志,发现采集任务输出的原始数据是正常的,问题出在数据处理任务读取环形缓冲区时,读到了“半截”数据。更诡异的是,用示波器量SPI总线,时序完全正确。
最后定位到:环形缓冲区的写指针和读指针,在Cortex-M7的双发射流水线下,出现了非原子操作。两个任务同时访问同一个全局变量,没有加锁。这个bug在调试模式下几乎不出现,因为调试器会插入断点改变时序。但Release优化一开,必现。
从那以后,我养成了一个习惯:任何被两个以上任务访问的全局变量,要么用信号量,要么用互斥锁,要么用关中断——总之,不能裸奔。
信号量:不只是计数的“令牌”
很多人把信号量当成“计数器”来理解,这没错,但容易忽略它的核心作用:同步。
二值信号量 vs 计数信号量
二值信号量只有0和1两种状态,本质上就是“有没有资源”。我常用它来做“事件通知”——比如一个任务等待外部中断触发,中断服务程序里释放信号量,等待任务拿到信