文章目录
1. 前言简介
Linux系统中,CPU被两类程序占用:
- 一类是进程和线程(kernel线程),也称进程上下文;
- 一类是各种中断、异常的处理程序,也称中断上下文;
为什么要引入CPUidle?
- 当CPU没有任务空闲时,让CPU置为WFI(Wait for interrupt)低功耗状态, 以节省功耗。
怎么实现CPUidle?
- 在系统的第一个进程(pid为 0的零号进程)完成初始化任务之后,将其转变为idle进程(如评论,也称上帝进程);
- 当其他进程都没有被调度时,idle进程就被调度,准备让CPU进入idle状态;
- 最终,由idle进程调用idle指令(比如ARM chip 的
WFI
指令),让CPU进入idle状态。
2. Linux CPUidle 原理介绍
2.1 CPUidle 总体框架
2.1.1 外部模块:kernel sched
- 系统调度模块,没任务调度时系统便进入idle(2.2节介绍)。负责实现idle线程的通用入口逻辑,包括idle模式选择、idle进入等;
/kernel/sched/idle.c
2.1.2 核心模块:cpuidle core
- 以函数调用形式向上层外部模块sched提供接口;
- 以sysfs的形式,向用户空间提供接口;
- 向下层硬件平台相关cpuidle drivers提供注册管理接口;
- 向idle算法模块governors提供注册和管理接口;
/drivers/cpuidle/cpuidle.c
,governor.c
,sysfs.c
,driver.c
2.1.3 平台相关:cpuidle drivers
- 负责硬件平台相关idle机制的实现,具体如何实现进入idle状态,什么条件下会退出等,下面分别是arm64芯片和mtk公司芯片平台相关代码;
/drivers/cpuidle/cpuidle-arm64.c
,cpuidle-mtk_acao.c
2.1.4 算法模块:cpuidle governors
- 选择要进入哪个idle 状态的算法模块相关代码;
/drivers/cpuidle/governors/*
2.2 Linux Idle sched 模块核心构架
系统开机过程中,跑在第一个cpu 的kernel 0号进程从start_kernel
到rest_init
做了各种初始化,最后该linux kernel 0 进程被置为idle 进程。如果是多核的CPU,其他核也会从secondary_start_kernel
进口做完相关的初始化后被置为idle 进程。
如下ps -A
命令结果,可以看到1号 init 进程和2号 kthreadadd 进程的 ppid (父进程id)是0 号进程初始化得到(上面流程代码kernel_thead
fork创建).
如上面的代码流程图和《Linux cpuidle framework(1)_概述和软件架构 》介绍,idle进程一直在检测系统当前是否需要调度,如果不需要调度(!need_resched(),即系统Idle 空闲),则执行进入idle的过程:
cpuidle_select
,通过cpuidle governor,选择一个cpuidle statecpuidle_enter
,通过cpuidle state,进入该idle状态cpuidle_reflect
,通知cpuidle governor,更新状态
2.3 选择idle状态的考量依据
由于SoC(System on Chip,片上系统,比如MTK 公司的G90 MT6785,包括CPU、GPU等)越来越复杂,芯片各种模块资源也多,所有设计多种级别idle状态(在MTK 的SoC一般有 wfi, cpuoff, cluster_off, sodi, dpidle, sodi3 状态)。idle 状态下关闭的系统资源越多,idle的功耗就越低,但对应进入和退出该idle状态过程使用的延迟时间(exit_latency
,该字段在系统代码中表示进和退idle过程中消耗的时间)就越长。
- 对延迟较敏感的场合,可以使用低延迟、高功耗的idle(即比较浅的idle状态,进入过程消耗的时间也少);
- 对延迟不敏感的场合,可以使用高延迟、低功耗的idle(即比较深的idle状态,进入过程消耗的时间长,因为要关闭的系统资源多);
如下图,由于进入和退出idle 过程中消耗的功耗高,所以要保证在idle状态下驻留时间(last residency
)呆着足够长,才能达到省电的效果。 如果频繁地进入和退出更深层的idle反而会更耗电,因为进入和退出深层的idle过程的延迟时间比较大,而且进入和退出的过程中功耗也高。
怎么选择进入idle状态才能保证达到省电的效果(即上面 绿色的面积 > 红色的面积),这就是cpuidle governor 要做的工作了。《Linux cpuidle framework(4)_menu governor 》中介绍了menu governor,这个governor相对有点难,本文后面介绍相对简单的ladder governor。
3. Linux CPUidle 代码流程
3.1 cpuidle register driver and devices
3.2 cpuidle schedule
3.3 cpuidle enter
3.4 cpuidle register governor
3.5 cpuidle governor call – ladder
更多Linux cpuidle 相关文章:
《Linux CPUidle 原理和代码流程》https://wu-being.blog.csdn.net/article/details/102771007
《Linux cpuidle framework(1)_概述和软件架构 – wowo》
《Linux cpuidle framework(2)_cpuidle core – wowo》
《Linux cpuidle framework(3)_ARM64 generic CPU idle driver – wowo》
《Linux cpuidle framework(4)_menu governor – wowo》
Wu_Being博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
《Linux CPUidle 原理和代码流程》:
https://blog.csdn.net/u014134180/article/details/102771007