4. 任务调度策略详解:抢占式调度、时间片轮转调度、合作式调度

调度策略,说白了就是RTOS决定「下一个该谁跑」的规则。我做了这么多年嵌入式,见过不少工程师一上来就选抢占式,结果系统跑起来各种抖;也有人死磕合作式,最后发现实时性根本满足不了。其实没有银弹,关键看你的应用场景。

今天咱们就把这三种调度策略掰开揉碎,讲讲它们怎么工作、各自有什么坑、以及什么时候该用哪个。

4.1 抢占式调度(Preemptive Scheduling)

这是RTOS里最常用的策略。它的核心逻辑是:谁优先级高,谁就先跑。哪怕低优先级任务正在执行,只要高优先级任务就绪了,系统会立刻打断它,把CPU抢过来。

核心机制:每个任务都有优先级,调度器在每个系统Tick中断里检查是否有更高优先级的任务就绪。如果有,就做上下文切换。

我刚开始用FreeRTOS时,犯过一个低级错误:把两个中断服务函数里的任务优先级设得一样高,结果系统频繁切换,LED灯都在闪。后来才明白,抢占式调度对优先级设计的要求非常高。

适用场景

  • 硬实时系统:比如电机控制、工业PLC,必须保证高优先级任务在确定时间内响应
  • 事件驱动型系统:按键响应、传感器中断,需要立刻处理
  • 多任务负载不均:有些任务偶尔才跑,但一跑就必须马上完成

我曾经踩过的坑:优先级反转。低优先级任务拿了互斥锁,高优先级任务等锁,结果中优先级任务一直跑,高优先级任务活活饿死。后来用优先级继承协议才解决。

4.2 时间片轮转调度(Round-Robin Scheduling)

这个策略就公平多了。所有同优先级任务轮流跑,每人分一个固定时间片。时间到了,不管任务跑没跑完,都得让给下一个。

说白了,就是「一人一筷子,轮流吃」。我习惯把时间片设成1ms到10ms之间,太短了切换开销大,太长了实时性又差。

适用场景

  • 人机交互界面:LCD刷新、触摸扫描,不需要多快,但不能卡顿
  • 后台任务:日志记录、状态监控、数据统计
  • 同优先级任务较多:比如多个传感器轮流采集数据

我的经验:时间片轮转最适合「大家差不多重要」的场景。如果某个任务特别紧急,就别用轮转,给它单独提优先级。

4.3 合作式调度(Cooperative Scheduling)

这个策略最「佛系」。任务自己决定什么时候让出CPU,调度器从不主动打断。任务必须主动调用taskYIELD()或等待某个事件,才会切换。

你想想看,这就像一群人开会,每个人讲完了自己说「我讲完了,下一个」。如果有人一直讲不停,后面的人就只能干等。

适用场景

  • 资源极度受限:RAM只有几KB的MCU,不需要内核维护Tick定时器
  • 任务数量少且确定:比如一个采集任务、一个通信任务、一个显示任务
  • 对确定性要求极高:没有抢占,就没有优先级反转,行为完全可预测

我曾经翻车的一次:在一个合作式系统里,有个任务里写了while循环等待外设就绪,结果外设一直没就绪,整个系统卡死了。从那以后,我规定合作式系统里绝不允许死等,必须用状态机。

4.4 三种策略对比

特性 抢占式 时间片轮转 合作式
实时性 低(取决于任务)
资源开销 高(需要Tick中断、栈空间)
编程复杂度 高(需处理优先级反转、竞态)
公平性 差(高优先级独占) 取决于任务设计
典型应用 电机控制、工业自动化 GUI、后台服务 极简系统、裸机迁移

4.5 知识体系结构图

下面这张图帮你理清三种调度策略的核心逻辑和适用场景:

任务调度策略知识体系 任务调度策略 抢占式调度 时间片轮转调度 合作式调度 高优先级抢占低优先级 需处理优先级反转 适用:电机控制、工业PLC 同优先级轮流执行 固定时间片(1-10ms) 适用:GUI、后台任务 任务主动让出CPU 无抢占,行为可预测 适用:极简系统、裸机迁移 选择策略 = 实时性要求 × 资源限制 × 任务特性

4.6 实际选型建议

嗯,这里我直接给结论吧:

  • 做运动控制:必须用抢占式。电机换向、电流环这些任务,延迟1ms都可能出问题。
  • 做人机界面:时间片轮转就够了。LCD刷新慢一点没关系,但不能卡死。
  • 做传感器采集:如果MCU资源紧张,合作式调度配合状态机,反而更稳定。

我的习惯:实际项目中经常混合使用。比如抢占式调度跑实时任务,时间片轮转跑后台任务。FreeRTOS和uC/OS都支持这种混合模式。

最后说一句:调度策略没有绝对的好坏,只有合不合适。你想想看,一个跑在Cortex-M0上的温湿度采集器,非要上抢占式调度,那不是杀鸡用牛刀吗?


公众号:蓝海资料掘金营,微信deep3321