1. 为什么你的RTOS任务卡在while循环里出不来?
前几天有个朋友在调试FreeRTOS时遇到了一个奇怪的问题:高优先级任务明明已经修改了全局变量update_flag的值,但低优先级任务中的while(!update_flag)循环却死活跳不出来。这就像两个人约好见面,A已经到了约定地点并发了消息,但B的手机却一直收不到通知,还在原地傻等。
这个问题在RTOS开发中特别常见,尤其是在开启了编译器优化的情况下。我当年第一次遇到时也百思不得其解,后来才发现是编译器优化和volatile关键字在"捣鬼"。简单来说,当编译器开启优化后,它会自作聪明地认为:"这个while循环里的update_flag又没人修改,干嘛每次都去内存里读取?直接缓存起来用不是更快吗?"但它不知道的是,在另一个任务中,这个变量正在被偷偷修改。
2. 编译器优化是如何"坑"了你的代码?
2.1 编译器优化的两面性
编译器优化就像个热心的管家,总想帮你把家里收拾得更整洁高效。它会做很多事情:
- 删除"没用"的代码
- 把变量缓存在寄存器里
- 重新排列指令顺序提高效率
但这位管家有时候太热心了,特别是在RTOS这种多任务环境下。来看个实际的例子:
// 高优先级任务
void HighPriorityTask(void *pvParameters) {
if(condition) {
shared_var = 1; // 修改共享变量
}
vTaskDelay(10);
}
// 低优先级任务
void LowPriorityTask(void *pvParameters) {
while(shared_var == 0); // 等待变量变化
// 后续代码...
}
开启优化后,编译器可能会把低优先级任务中的while循环优化成这样:
; 优化前
loop:


6694

被折叠的 条评论
为什么被折叠?



