文章目录[隐藏]
核心速览

调度的概念
Zephyr 是一个多线程操作系统。线程是调度的基本单位。每个线程都是一个独立的执行流,拥有自己的上下文(如程序计数器、寄存器、栈空间)和优先级。内核的工作就是管理这些线程,并根据调度策略在它们之间切换。
- 调度程序确定哪个线程被允许在任何时间点执行;这个线程被称为当前线程。
-
调度程序可以在多个时间点更改当前线程的身份,也就是将 CPU 的执行从一个线程切换到另一个线程。这些时间点称为*重新调度点。
-
当线程自愿启动将自身转换为挂起或等待状态的操作时,它就会进入睡眠状态。
每当调度程序更改当前线程的身份,或者当前线程的执行被 ISR 替换时,内核首先会保存当前线程的 CPU 寄存器值。当线程稍后恢复执行时,这些寄存器值会被恢复。

调度算法
内核调度程序会选择优先级最高的就绪线程作为当前线程。当存在多个相同优先级的就绪线程时,调度程序会选择等待时间最长的线程。
三种调度算法
Zephyr 支持多种调度算法,可以根据应用需求进行选择:
- 传统调度器 (Traditional Scheduler):这是默认的调度器,实现了上述的“基于优先级的抢占式调度”和“时间分片”。它使用多个就绪队列,每个优先级一个队列,查找下一个要运行的线程非常高效。
- 最早截止期优先调度 (Earliest Deadline First, EDF):
- 这是一种高级的实时调度算法,通过
CONFIG_SCHED_DEADLINE启用。 - 在这种模式下,调度器选择线程的标准不再是固定的优先级,而是截止时间 (Deadline)。拥有最早截止时间的线程将被优先执行。
- 这对于需要保证任务在特定时间点前必须完成的硬实时系统(Hard Real-time Systems)非常有用。
- 这是一种高级的实时调度算法,通过
- Meta-IRQ 调度:这是一种特殊的、高优先级的调度方式,允许线程在比所有常规线程都高的优先级(但低于硬件中断)上运行,用于处理非常紧急但又不能在中断服务程序(ISR)中完成的任务。
ISR 的执行优先于线程的执行,因此除非中断已被屏蔽,否则当前线程的执行可能随时被 ISR 取代。这适用于协作型线程和抢占式线程。
就绪队列三种实现
- 简单链表(
CONFIG_SCHED_SIMPLE)- 线程数很少(3个以内)、优先级变化不频繁场景
- 占用极小代码空间(约2KB)
- 插入/删除操作非常快O(n)
- 线程数增多时,查找最高优先级线程会变慢

- 优先级队列(
CONFIG_SCHED_MULTIQ)- 优先级种类不多、线程数适中
- RAM 占用较多,每种优先级
- 查找、调度操作在常数时间级 O(1)
- 不适用于需按截至时间排序、多核亲和性场景

- 红黑树(
CONFIG_SCHED_SCALABLE)- 线程数较多(几十、上百甚至更多)
- 代码体积约2KB
- 插入/删除操作稍慢
- 线程数增多时,查找/插入/删除性能在对数时间级O(log n)
一句话模型 “最小数字优先,协作不抢占,同级看时间片,高优来就走,没人跑 Idle。”

调度方式
协作式时间分片
在协作式调度 (Cooperative Scheduling)中,一个正在运行的线程将一直持有 CPU,直到它主动放弃 CPU 使用权。调度器本身不会强制中断线程。
为了克服这些问题,协作线程可以不时主动放弃 CPU,以允许其他线程执行。线程可以通过两种方式放弃 CPU:
- 调用
k_yield(): 将线程置于调度程序的就绪线程优先级列表的末尾; - 调用
k_sleep(): 线程在指定的时间内处于非就绪状态;
简单比喻: 就像一个开放的讨论组,一个成员(线程)可以一直发言,直到他自己觉得说完了,主动停下来让给别人。如果有人滔滔不绝不肯停,其他人就永远没机会说话。
抢占式时间分片
在抢占式调度 (Preemptive Scheduling)中,调度器(Scheduler) 拥有完全的控制权,可以随时中断一个正在运行的线程,并将 CPU 分配给另一个线程。这种中断(即“抢占”)的发生通常是基于优先级和时间片。
不同优先级:抢占
同优先级:时间片轮转
简单比喻: 就像一个严格的老师管理课堂,每个学生(线程)只有固定的发言时间(时间片)。时间一到,老师会立刻打断,让下一个学生发言。如果有更重要的事(高优先级线程),老师会立即处理。
配置选项
CONFIG_TIMESLICING:启用时间片调度功能(仅对“可抢占线程”且在指定优先级范围内生效)-
CONFIG_TIMESLICE_SIZE: 指定每个时间片长度(单位:系统时钟 tick -
CONFIG_TIMESLICE_PRIORITY:定义一个阈值优先级(数值,记住:数值越小优先级越高)。

CPU空闲(CPU Idle)机制
概念
在 Zephyr 中,CPU 空闲是电源管理框架的核心部分。当系统中没有任何线程需要运行时(即所有线程都在等待事件、休眠或被挂起),空闲线程(idle thread)就会获得 CPU 控制权。空闲线程的主要职责就是让 CPU 进入低功耗状态,以节省能源。
基本原理
Zephyr 内核在调度器发现没有可执行的应用程序线程时,会切换到内置的空闲线程。这个线程会调用电源管理子系统提供的接口,尝试让 CPU 进入最深的可用睡眠状态。
电源状态
Zephyr 定义了多种电源状态,CPU 可以在空闲时进入这些状态。这些状态通常与处理器的特定低功耗模式相关联。当系统空闲时,电源管理子系统会根据距离下一个定时器事件的时间长短,来决定进入哪种睡眠状态。如果下一个事件很遥远,系统就可以进入更深的睡眠状态,以获得更大的功耗节省。
Tickless Idle(无滴答空闲)
- 在传统的 RTOS 中,系统定时器(System Tick)会以固定的频率(例如,每 1-10 毫秒)产生中断,即使系统处于空闲状态。这会周期性地唤醒 CPU,造成不必要的功耗。
- Zephyr 支持 Tickless Idle 模式。在这种模式下,当系统进入空闲状态时,内核会停止周期性的系统定时器中断。同时,它会计算出下一个需要处理的事件(比如一个线程的超时)的确切时间,并对定时器硬件进行编程,使其在那个精确的时刻产生一个中断。
- 这样,CPU 可以在两个事件之间保持长时间的深度睡眠,而不会被不必要的定时器中断唤醒,从而极大地降低了系统在空闲时的功耗。
配置选项
您可以通过 Kconfig 选项来配置 Zephyr 的电源管理和 CPU 空闲行为。一些关键的配置项包括:
CONFIG_PM=y:启用电源管理模块。CONFIG_PM_DEVICE=y:启用设备电源管理,允许外设在不使用时进入低功耗状态。CONFIG_TICKLESS_IDLE=y:启用 Tickless Idle 功能。这是实现高效节能的关键。CONFIG_TICKLESS_KERNEL=y:这是一个更高级的模式,它不仅在空闲时,在线程等待内
了解 Heiweilu的小世界 的更多信息
订阅后即可通过电子邮件收到最新文章。







