3. 任务调度策略:固定优先级调度(RMS)、单调速率调度(RMS)、最早截止时间优先(EDF)、比例公平调度
好,咱们今天聊聊任务调度策略。这是ADAS系统的核心问题之一。
你想想看,一个ADAS系统里,有摄像头数据要处理,有雷达点云要融合,有控制指令要下发。这么多任务挤在一起,谁先跑谁后跑?调度策略就是回答这个问题的。
我个人习惯把调度策略分成两大类:静态优先级和动态优先级。咱们一个一个来看。
3.1 固定优先级调度(FPS)
固定优先级调度,说白了就是每个任务生下来就有一个固定的优先级。高优先级的任务永远先跑,低优先级的任务只能等。
我在项目中遇到过这样一个场景:一个ADAS控制器里,CAN报文接收中断的优先级设得特别高,结果导致图像处理任务经常被饿死。嗯,这就是固定优先级调度的典型问题——优先级反转和任务饿死。
核心要点:
- 优先级一旦设定,运行期间不变
- 实现简单,系统开销小
- 适合任务数量少、周期固定的场景
- 需要人工仔细分配优先级
我的经验:在ADAS系统中,我通常把安全相关的任务(如制动控制)设为最高优先级,感知任务次之,诊断和日志任务放最低。但要注意,别把太多任务塞进同一个优先级,否则调度器会变成轮询,失去优先级的意义。
3.2 单调速率调度(RMS)
RMS其实是固定优先级调度的一种特例。它的规则很简单:周期越短的任务,优先级越高。
为什么会这样?因为周期短的任务通常意味着更紧迫,需要更频繁地执行。你想想看,一个10ms周期的控制任务,和一个100ms周期的诊断任务,谁更紧急?当然是控制任务。
RMS的调度条件:
U = Σ (Ci / Ti) ≤ n * (2^(1/n) - 1)
其中:
- U: CPU利用率
- Ci: 任务i的最坏执行时间
- Ti: 任务i的周期
- n: 任务数量
当任务数量n趋于无穷时,这个利用率上限大约是69.3%。也就是说,用RMS调度,CPU利用率超过69.3%就可能出现任务超时。
注意:我曾经在一个项目中,把RMS用在了非周期任务上,结果调度完全乱套了。RMS只适用于周期任务,非周期任务需要另外处理。
3.3 最早截止时间优先(EDF)
EDF是动态优先级调度的代表。它的逻辑很直观:谁的截止时间最近,谁就先跑。
我记得第一次用EDF时,觉得这玩意儿太聪明了。它不像RMS那样死板,而是根据任务的实时状态动态调整优先级。理论上,EDF的CPU利用率可以达到100%。
EDF的优势:
- 理论上CPU利用率可达100%
- 对任务周期和截止时间没有特殊要求
- 适合混合周期任务场景
EDF的劣势:
- 实现复杂,系统开销大
- 过载时性能急剧下降(多米诺效应)
- 难以预测最坏情况
避坑指南:我曾经在一个ADAS项目中尝试用EDF调度图像处理任务。结果系统负载一高,所有任务都开始错过截止时间,整个系统像多米诺骨牌一样崩溃。后来我学乖了——EDF虽然理论完美,但在嵌入式系统中,可预测性比理论最优更重要。
3.4 比例公平调度(PFS)
比例公平调度,这个名字听起来有点绕。其实它的核心思想是:每个任务按照权重分配CPU时间。
举个例子,任务A权重是2,任务B权重是1。那么在单位时间内,任务A获得的CPU时间应该是任务B的两倍。这种调度方式在多媒体处理中很常见,但在ADAS中也有用武之地。
PFS的适用场景:
- 多个任务需要公平共享CPU资源
- 任务对延迟不敏感,但对吞吐量有要求
- 需要保证每个任务都能获得一定比例的CPU时间
我个人觉得,PFS在ADAS中更适合后台任务,比如日志记录、数据上传等。对于硬实时任务,还是用RMS或FPS更靠谱。
3.5 四种调度策略对比
| 调度策略 | 优先级类型 | CPU利用率上限 | 实现复杂度 | 适用场景 |
|---|---|---|---|---|
| FPS | 静态 | 取决于任务集 | 低 | 任务少、周期固定 |
| RMS | 静态 | 69.3%(n→∞) | 低 | 周期任务 |
| EDF | 动态 | 100% | 高 | 混合周期、软实时 |
| PFS | 动态 | 取决于权重 | 中 | 公平共享、后台任务 |
重要提醒:在实际ADAS项目中,很少只用一种调度策略。我通常的做法是:硬实时任务用RMS,软实时任务用EDF,后台任务用PFS。混合使用才能发挥各自优势。
3.6 我的选择建议
说了这么多,到底该选哪种?
我个人建议:
- 安全关键任务(制动、转向):用RMS,可预测性强
- 感知任务(摄像头、雷达):用EDF,能应对突发负载
- 诊断和日志:用PFS,别让它们影响主任务
嗯,调度策略没有银弹。关键是要理解你的任务特性,然后选择合适的策略。我在项目中吃过不少亏,希望你能少走弯路。
最后说一句:不管用哪种调度策略,一定要做最坏情况分析。我曾经以为系统负载只有60%,结果一个极端场景下CPU飙到95%,所有任务都超时了。从那以后,我每次都会留出至少30%的余量。