Skip to content

1.6 调度器 ​

这节要搞懂:好几个任务都想跑,谁说了算。 需要基础:1.5 ⭐ 本章重点

一、什么是调度器 ​

调度器(Scheduler)是操作系统内核的核心部件,负责决定在每一时刻由哪个任务占用 CPU。FreeRTOS 采用基于优先级的抢占式调度:始终运行处于就绪状态中优先级最高的任务。

打个比方:调度器就是排班主管。所有员工都想上工,由他一个人说了算。

他的规则只有一句话:

谁的优先级最高,而且现在能跑,就让谁跑。

二、什么是优先级 ​

优先级(Priority)表示任务的重要程度。数值越大,越优先获得 CPU。

在 ESP32 上范围是 0 ~ 24:

优先级给谁用
0系统保留(空闲任务专用),你别用
1 – 4不着急的事:打日志、统计、上报数据
5 – 9⭐ 平时就填这个范围:显示、传感器、按键
10 以上系统的 WiFi、网络已经在用,别去挤

:

拿不准就全填 5。等哪个功能反应慢了,再把它调到 6。

三、什么是抢占 ​

抢占(Preemption)指的是:当一个优先级更高的任务变为就绪状态时,内核会立即中断当前正在运行的任务,转而执行高优先级任务。

举个例子:

  • 任务 A:优先级 3,正在慢慢打印日志
  • 任务 B:优先级 6,在等按键

你一按按键,任务 B 立刻醒来,把正在跑的任务 A 一脚踹开,自己上:

这就是为什么按键任务要给高优先级 —— 重要的事总能第一时间响应。

四、优先级一样怎么办 ​

时间片轮转:优先级相同的任务,内核会让它们轮流执行,每人一小段时间。

你一下我一下,看起来就像同时在跑。

五、什么是空闲任务 ​

空闲任务(Idle Task)是调度器启动时自动创建的一个优先级为 0 的任务。当没有任何其他任务可运行时,CPU 就执行它。

它负责回收被删除任务占用的内存,所以必须保证它有机会运行。

六、高优先级任务的责任 ⭐ ​

最经典的翻车现场

高优先级的任务,绝对不能一直不"睡"。

c
void task_high_priority(void *pvParameters)
{
    while (1) {
        do_something();
        // ❌ 这里没有 vTaskDelay!
    }
}

后果:它会一直霸占 CPU,所有优先级比它低的任务全部饿死,包括负责回收内存的空闲任务。

系统会打印这句话提醒你: Task watchdog got triggered. The following tasks did not reset the watchdog in time

看到这句话,就去检查是不是哪个任务忘了 vTaskDelay。

七、时间是怎么算的 ​

Tick(时钟节拍) 是 FreeRTOS 的时间基本单位。内核靠一个硬件定时器周期性产生 tick 中断,所有的延时和超时都按 tick 计算。

你不需要关心一个 tick 是多久,只要永远用这个宏来换算:

c
vTaskDelay(pdMS_TO_TICKS(500));    // ✅ 睡 500 毫秒,这样写就对了
vTaskDelay(500);                   // ❌ 别这么写!这是 500 个 tick,不是 500 毫秒

本节要点 ​

  • 调度器 = 决定谁用 CPU 的部件,规则是"优先级最高且能跑的先跑"
  • 优先级新手统一填 5,需要快速响应的填 6
  • 抢占 = 高优先级任务一就绪,立刻打断当前任务
  • 优先级相同则轮流执行
  • ⭐ 高优先级任务必须会"睡",否则饿死所有人
  • 延时永远写 pdMS_TO_TICKS(毫秒数)

动手试试 ​

  1. 建三个任务,优先级分别是 3、5、7,各自打印自己的名字,观察输出规律。
  2. 把优先级 7 的那个任务的 vTaskDelay 删掉,看看另外两个还能不能打印。
  3. 把两个任务设成同样的优先级,验证它们是不是在轮流打印。