Linux CPUidle 原理和代码流程

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 模块核心构架

Linux 原生 Idle 构架
系统开机过程中,跑在第一个cpu 的kernel 0号进程start_kernelrest_init 做了各种初始化,最后该linux kernel 0 进程被置为idle 进程。如果是多核的CPU,其他核也会从secondary_start_kernel进口做完相关的初始化后被置为idle 进程。

如下ps -A 命令结果,可以看到1号 init 进程2号 kthreadadd 进程的 ppid (父进程id)是0 号进程初始化得到(上面流程代码kernel_thead fork创建).
ps -A
如上面的代码流程图和《Linux cpuidle framework(1)_概述和软件架构 》介绍,idle进程一直在检测系统当前是否需要调度,如果不需要调度(!need_resched(),即系统Idle 空闲),则执行进入idle的过程

  • cpuidle_select,通过cpuidle governor,选择一个cpuidle state
  • cpuidle_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过程的延迟时间比较大,而且进入和退出的过程中功耗也高。
cpu 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章