3. 实时性优化:任务优先级设计、中断响应优化、时间片管理、看门狗策略
实时性,说白了就是系统对外部事件的响应速度。我见过太多项目,硬件选型没问题,算法也没毛病,但系统就是跑不稳。为什么?实时性没做好。今天咱们就聊聊这块的实战经验。
3.1 任务优先级设计——别让重要的事排队
任务优先级设计,是实时系统的第一道防线。我习惯把任务分成三类:
- 硬实时任务:错过截止时间就是事故。比如急停、安全联锁。
- 软实时任务:偶尔延迟可以接受。比如数据采集、状态刷新。
- 非实时任务:有空再做。比如日志记录、界面刷新。
优先级分配有个基本原则:紧急且重要的任务优先级最高。但这里有个坑——优先级反转。
我曾经在一个运动控制项目中遇到过这问题。一个高优先级的伺服控制任务,因为等待一个低优先级的通信任务释放共享内存,结果被一个中优先级的界面刷新任务卡了整整 200ms。电机直接抖了一下,产品报废了。
解决方案?我推荐两种:
- 优先级继承:低优先级任务临时提升到高优先级,快速释放资源。
- 优先级天花板:访问共享资源的任务,优先级直接拉到最高。
3.2 中断响应优化——快进快出
中断是实时系统的核心机制。但很多人把中断服务程序(ISR)写得又长又臭。你想想看,中断里做浮点运算、打印日志、甚至调用延时函数——这不是自找麻烦吗?
中断优化的核心原则就四个字:快进快出。
| 操作 | ISR 中做? | 说明 |
|---|---|---|
| 读取硬件寄存器 | ✅ 可以 | 越快越好,直接读 |
| 设置标志位 | ✅ 可以 | 通知任务处理 |
| 浮点运算 | ❌ 不建议 | 上下文保存开销大 |
| 打印日志 | ❌ 绝对不行 | 阻塞且耗时 |
| 调用延时函数 | ❌ 禁止 | 中断里不能阻塞 |
我记得有个项目,现场设备频繁触发中断,系统响应越来越慢。查了半天,发现 ISR 里有个 printf 函数,每次中断都往串口打印数据。串口速度 9600bps,打印一次要 1ms 多。中断一多,CPU 全耗在打印上了。
正确的做法是:ISR 里只做最必要的事——读数据、清标志、发信号。真正的处理交给任务去做。
3.3 时间片管理——别让一个任务霸占 CPU
时间片管理,说白了就是让多个任务轮流用 CPU。但怎么分?分多少?这里面有学问。
我常用的策略有三种:
- 固定时间片:每个任务分固定时长,轮转执行。适合任务周期相近的场景。
- 动态时间片:根据任务优先级和负载动态调整。适合复杂系统。
- 混合策略:高优先级任务用抢占式,低优先级任务用时间片轮转。这是我最常用的。
时间片大小怎么定?我有个经验公式:
时间片 = 任务最坏执行时间 × 1.5 ~ 2
太小了,上下文切换开销太大;太大了,低优先级任务响应太慢。我一般设 10ms 到 50ms 之间。
我曾经在一个多任务系统中,两个任务共享一个全局变量。一个任务写,一个任务读。时间片切换时,写任务刚写了一半就被切走了,读任务读到了半残数据。结果系统判断错误,直接停机了。
解决方案?用信号量或互斥锁保护共享资源。但注意,锁的粒度要小,持有时间要短。否则高优先级任务等锁,又回到优先级反转的老问题。
3.4 看门狗策略——系统的最后一道防线
看门狗,说白了就是系统的「保命符」。系统跑飞了、死锁了、任务卡住了,看门狗能帮你自动复位。
但看门狗不是随便喂的。我见过有人把看门狗喂在 main 循环里,结果任务卡死了,main 循环还在跑,看门狗照样喂——系统死得悄无声息。
正确的喂狗策略:
- 分层喂狗:每个关键任务独立喂狗,而不是统一喂。
- 窗口看门狗:必须在规定时间窗口内喂狗,太早或太晚都算失败。
- 独立看门狗:用硬件看门狗,别依赖软件定时器。
看门狗超时时间怎么设?我一般设为主任务周期的 3~5 倍。太短了容易误触发,太长了系统恢复太慢。
嗯,实时性优化这块,说到底就是「快、准、稳」。任务优先级要合理,中断要快进快出,时间片要分配得当,看门狗要喂得聪明。这些做好了,系统才能跑得稳、跑得久。