3、任务优先级与调度策略:抢占式调度、时间片轮转、合作式调度
调度策略,说白了就是操作系统决定「下一个该谁跑」的规则。我做了这么多年嵌入式,见过太多因为调度策略选错而翻车的项目。今天咱们就把这三种主流策略掰开揉碎讲清楚。
3.1 任务优先级——调度的核心依据
每个任务都有一个优先级数值。数值越小,优先级越高——这是RTOS里的惯例。嗯,也有反着来的,比如FreeRTOS就是数值越大优先级越高,但道理一样。
我在项目中遇到过一件事:有个同事把两个关键任务的优先级设成了相同值,结果系统跑起来后,一个任务死活抢不到CPU。为什么?因为时间片轮转没开,同优先级任务之间不会主动让出CPU。你看,优先级设计看似简单,坑却不少。
优先级设计的基本原则:
- 实时性要求高的任务,给高优先级
- 计算量大的任务,给低优先级
- 中断服务相关的任务,通常给最高优先级
- 空闲任务永远给最低优先级
3.2 抢占式调度——谁急谁先跑
抢占式调度,是RTOS最常用的策略。它的规则很简单:高优先级任务就绪后,立刻打断当前正在运行的低优先级任务。
你想想看,这就像急诊室。来了个危重病人,医生马上放下手头的普通门诊去抢救。等抢救完了,再回来继续看普通病人。
// 抢占式调度示例
void TaskA(void *param) {
while(1) {
// 优先级=5,中等优先级
printf("TaskA running\n");
vTaskDelay(100); // 主动阻塞,让出CPU
}
}
void TaskB(void *param) {
while(1) {
// 优先级=10,高优先级
printf("TaskB running\n");
// 注意:这里没有阻塞!
// TaskB会一直运行,TaskA永远得不到CPU
}
}
我曾经踩过的坑:高优先级任务如果一直不阻塞,低优先级任务会饿死。所以高优先级任务里一定要有阻塞点——比如等待信号量、消息队列,或者主动延时。
3.3 时间片轮转——公平是王道
时间片轮转,说白了就是「一人跑一会儿」。同优先级的任务,每个任务分到一个固定时间片,时间到了就切换到下一个。
我个人习惯在UI任务和后台计算任务上用时间片轮转。为什么?因为UI不能卡死,后台计算也不能太慢。两者优先级相同,时间片轮转,谁也别想独占CPU。
| 调度策略 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 抢占式 | 实时性要求高的系统 | 响应快,高优先级任务及时执行 | 低优先级任务可能饿死 |
| 时间片轮转 | 同优先级任务较多 | 公平,每个任务都有机会 | 上下文切换开销大 |
| 合作式 | 资源受限的简单系统 | 无锁,无竞态 | 一个任务卡死,全系统瘫痪 |
3.4 合作式调度——自觉才是美德
合作式调度,也叫非抢占式调度。任务自己决定什么时候让出CPU。你不让?那其他任务就等着。
我记得早期做8位单片机项目时,资源少得可怜,连个像样的RTOS都跑不起来。那时候就用合作式调度——每个任务里手动调用task_yield()来让出CPU。
// 合作式调度示例
void Task1(void) {
while(1) {
// 做一部分工作
do_some_work();
// 主动让出CPU
task_yield();
// 再做一部分工作
do_another_work();
task_yield();
}
}
void Task2(void) {
while(1) {
// 如果Task1不调用task_yield()
// Task2永远得不到执行
process_data();
task_yield();
}
}
我的建议:合作式调度适合任务数量少、每个任务执行时间短且可控的场景。比如简单的传感器采集、LED闪烁控制。千万别在复杂系统里用合作式——一个任务出bug死循环,整个系统就挂了。
3.5 三种策略的混合使用
实际项目中,很少只用一种策略。大多数RTOS都支持混合调度。比如FreeRTOS,默认是抢占式,但同优先级任务之间可以用时间片轮转。
我做过一个物联网网关项目,里面用了三种策略的混合:
- 中断处理任务:抢占式,最高优先级
- 网络协议栈任务:抢占式,高优先级
- UI刷新和日志记录:时间片轮转,中等优先级
- 后台数据统计:合作式,最低优先级
你看,不同任务对实时性的要求不同,调度策略也要「因材施教」。
3.6 调度策略选择指南
到底该用哪种?我总结了几条经验:
- 有硬实时任务(比如电机控制、音频处理)→ 必须用抢占式
- 同优先级任务多(比如多个UI界面)→ 开启时间片轮转
- 资源极度受限(比如4KB RAM的MCU)→ 考虑合作式
- 任务之间有数据共享 → 抢占式要加锁,合作式不用
核心原则:调度策略没有银弹。选型时要综合考虑实时性、资源开销、开发复杂度。我见过有人用抢占式调度做LED闪烁,结果因为优先级反转导致灯闪得乱七八糟——杀鸡用牛刀,反而出问题。
3.7 知识体系图
下面这张图展示了三种调度策略的核心逻辑和适用场景:
这张图把三种策略的核心特性、适用场景以及混合使用的关系都画出来了。你可以把它当作选型时的参考地图。
可可精品资料库