3. 任务调度基础:单速率任务、多速率任务、任务优先级与抢占
好,咱们今天聊聊任务调度。这是实时系统的核心,也是很多初学者容易踩坑的地方。
我记得刚接触dSPACE那会儿,总觉得任务调度不就是让几个函数轮流跑嘛,有什么难的?结果第一次做多速率项目,系统直接跑飞了。嗯,从那以后我再也不敢小看调度了。
3.1 单速率任务:最朴素的调度方式
单速率任务,说白了就是所有任务都按同一个频率执行。比如你有一个控制循环,固定每1ms跑一次。这就是单速率。
在dSPACE的RTI(Real-Time Interface)里,单速率任务通常对应一个定时器中断。你设置好周期,系统到点就触发。
核心特点:
- 所有任务共享同一个时间基准
- 任务执行顺序固定,没有优先级竞争
- 实现简单,适合功能单一的系统
我个人的习惯是,如果系统功能简单,比如就一个传感器采集加一个控制输出,我肯定用单速率。省心,不容易出幺蛾子。
但单速率有个硬伤:如果某个任务执行时间超过了周期,系统就崩了。你想想看,一个1ms的任务跑了2ms,下一个周期来了怎么办?
注意:单速率任务必须满足:最坏情况执行时间(WCET) < 任务周期。这是硬约束,没得商量。
3.2 多速率任务:现实世界的常态
实际项目中,很少有只用单速率的。比如一个汽车ECU,发动机控制要1kHz,车身控制100Hz就够了,诊断任务可能1Hz跑一次。这就必须用多速率。
多速率任务,就是不同任务按不同频率执行。在dSPACE里,你可以为每个任务单独设置周期。
| 任务类型 | 典型周期 | 优先级 |
|---|---|---|
| 发动机控制 | 1ms | 最高 |
| 变速箱控制 | 5ms | 高 |
| 车身控制 | 10ms | 中 |
| 诊断任务 | 1000ms | 低 |
这里有个坑:不同速率的任务之间怎么交换数据?我曾经见过一个项目,高速任务和低速任务共用一个全局变量,结果数据读到一半被覆盖了。嗯,这就是典型的资源竞争问题。
我的建议:多速率任务之间用双缓冲或者消息队列。别图省事直接用全局变量,血的教训。
3.3 任务优先级:谁说了算?
多速率任务多了,总得有个先后顺序。这就是优先级的作用。
在dSPACE的实时系统中,优先级通常用数字表示,数字越小优先级越高。比如优先级1的任务,永远比优先级2的任务先执行。
但优先级不是越高越好。我见过有人把所有任务都设成最高优先级,结果系统一直在处理高优先级任务,低优先级的永远没机会跑。这叫优先级反转,或者叫饿死。
优先级设置原则:
- 时间关键的任务给高优先级(比如安全相关的控制)
- 周期短的任务给高优先级(因为来不及等)
- 非关键、周期长的任务给低优先级
举个例子:一个安全气囊控制器,触发信号来了必须在1ms内响应。这种任务优先级必须最高。而一个仪表盘显示任务,晚个几十毫秒没人管你,优先级设低点就行。
3.4 抢占:高优先级说了算
抢占,就是高优先级任务来了,低优先级任务得让路。
在dSPACE里,默认是抢占式调度。也就是说,如果一个低优先级任务正在执行,突然来了一个高优先级任务,系统会立刻保存低优先级任务的上下文,切换到高优先级任务去执行。
等高优先级任务跑完了,再回来接着跑低优先级任务。
注意:抢占会导致上下文切换开销。如果切换太频繁,系统效率会下降。我曾经在一个项目里,任务周期设得太短,结果系统70%的时间都在做上下文切换,真正干活的时间只有30%。
那怎么避免?两个办法:
- 合理设置周期:别把周期设得太短,够用就行
- 使用临界区:在关键操作前后关中断,防止被抢占
但临界区也有代价。关中断时间太长,会影响实时性。我一般建议临界区控制在几十微秒以内,别超过100微秒。
3.5 一个实际案例
说个我经历过的项目吧。一个电机控制平台,需要同时做电流环、速度环和位置环。
电流环最快,需要10kHz(100微秒周期)。速度环1kHz(1ms周期)。位置环100Hz(10ms周期)。
我当时的配置是这样的:
- 电流环任务:优先级1,周期100微秒
- 速度环任务:优先级2,周期1ms
- 位置环任务:优先级3,周期10ms
一开始跑得好好的。后来加了通信任务,优先级设成了0(最高)。结果通信任务一跑,电流环就被抢占了,电机开始抖动。
排查了半天才发现,通信任务的优先级设得太高了。其实通信任务对实时性要求没那么高,丢一包数据无所谓,但电流环丢一个周期电机就抖。
最后把通信任务优先级降到4,问题解决。
经验总结:优先级不是越高越好,而是越合适越好。把优先级给真正需要实时响应的任务,别浪费在非关键任务上。
3.6 小结
任务调度这块,说白了就是三个问题:
- 任务跑多快(单速率还是多速率)
- 谁先跑(优先级)
- 能不能打断(抢占)
搞清楚了这三个问题,实时系统的基本框架就搭起来了。剩下的就是细节调优,比如任务间通信、资源保护这些。
嗯,下一章咱们聊聊任务间通信,那又是一个容易踩坑的地方。