
04 · 调度器——经理排班🍴 生活类比:经理的三大原则抢占式:主厨(高优先级)说"这锅必须现在处理",普通厨师立刻让位——高优先级任务随时打断低优先级任务。时间片轮转:两个同级别的厨师都用灶台,经理让他们每人炒 1 分钟换人——同级任务轮流执行。空闲任务:没人点单时,保洁大爷打扫卫生——Idle 任务兜底。🖼 静态类比插图:CPU 灶台占用时间轴(时间片轮转 + 抢占)同级任务时间片轮转(每 1ms 换人): ┌───────┬───────┬───────┬───────┬───────┬───────┬────▶ 时间 │ TaskA │ TaskB │ TaskC │ TaskA │ TaskB │ TaskC │ └───────┴───────┴───────┴───────┴───────┴───────┘ 高优先级 TaskX 就绪 → 随时插队(抢占): ┌───────┐ │ TaskA │ └───┬───┘ │ TaskX 就绪!A 被打断 ▼ ┌───────────────┬───────┬───────┬────▶ 时间 │ TaskX 抢占运行 │ TaskA │ TaskB │ ← A 回到就绪队列排队 └───────────────┴───────┴───────┴────调度全景情形调度器行为高优先级任务就绪立即抢占 CPU同级任务就绪时间片轮转(SysTick 每 1ms 切一次)高优先级任务 osDelay挂起等待,低优先级捡漏运行所有任务都在等Idle 任务运行(CPU 空闲,可低功耗)/* 任务A:优先级 High,每 2s 打印一次 */voidTaskA(void*arg){for(;;){printf("[A] high-priority work\r\n");osDelay(2000);}}/* 任务B:优先级 Normal,每 100ms 打印一次 */voidTaskB(void*arg){for(;;){printf("[B] low-priority work\r\n");osDelay(100);}}/* 现象:A 每次醒来必定先执行(抢占 B),B 只能在 A 睡觉时干活 */🖼 静态类比插图:任务状态机(厨师的一生)┌────────┐ 调度器选中 ┌────────┐ │ 就绪 │ ─────────────▶ │ 运行 │ │ Ready │ ◀───────────── │ Running│ └────────┘ 被抢占/时间片到 └───┬────┘ ▲ ▲ │ │ │ osDelay / 等队列 │ │ │ / 等信号量 ▼ │ │ 延时到/数据到 ┌────────┐ │ └────────────── │ 阻塞 │ │ │ Blocked│ │ └────────┘ │ Resume 恢复 ┌────────┐ └──────────────── │ 挂起 │ vTaskResume │Suspend │ └────────┘ 候场(就绪) → 炒菜(运行) → 等食材(阻塞) → 被经理点名休息(挂起)⚠优先级反转(进阶坑):低优先级任务拿着互斥量不放,高优先级任务在等这个量——中间还有个中优先级任务插队。FreeRTOS 的互斥量有优先级继承机制缓解(低优先级临时提升到等待者的级别),但根本方案是合理设计优先级层次。