大家好,欢迎来到IT知识分享网。
在 Linux 操作系统中,Idle 进程(又叫 Swapper 进程)的 pid 号是 0,是所有进程的祖先,它是在 Linux 初始化阶段从无到有创建的一个内核线程。stark_kernel() 函数初始化内核需要的所有数据结构,激活中断,创建另一个叫进程 1 的内核线程(init 进程)。新创建内核线程的 PID 为 1,并与进程 0 共享进程所有的内核数据结构。创建 init 进程后,进程 0 执行无限循环, cpu_idle_loop() 函数,只有当没有其它进程处于 TASK_RUNNING 状态时,调度器才会选择进程 0,也就是执行 Idle 线程,让 CPU 进入 Idle 模式。
当 CPU 进入比较深层次的 Idle 模式时,为了达到最大程度的节省功耗,CPU 会把系统时钟给关闭掉。那么怎么保证 CPU 从 Idle 模式重新进入工作模式,从而保证系统正常运行呢?本文主要探讨低功耗定时器在该情况下扮演什么样的角色。
Idle的执行流程
这里先大概的列出 Idle 进程的执行流程,怎么执行到让 CPU 进入各级 Idle 模式。
Idle 进程创建
Linux Kernel 会在系统启动完成后,在 Idle 进程中,处理 CPUIdle 相关的事情。在多核系统中,CPU 启动的过程是,先启动主 CPU,启动过程和传统的单核系统类似。其函数调用关系如下:
stext –> start_kernel –> rest_init –> cpu_startup_entry
而启动其它 CPU,可以有多种方式,例如 CPU hotplug 等,启动过程:
secondary_startup –> __secondary_switched –> secondary_start_kernel –> cpu_startup_entry
无论是上述的哪种启动,最终都会运行至 cpu_startup_entry 函数,在这个函数中,最终程序会掉进无限循环里 cpu_idle_loop。到此,Idle 进程创建完成。
Tickless 和 CPUIdle 的关系
Tickless 是指动态时钟,即系统的周期 Tick 可动态地关闭和打开。这个功能可通过内核配置项 CONFIG_NO_HZ 打开,而 Idle 正是使用了这项技术,使系统尽量长时间处于空闲状态,从而尽可能地节省功耗.
打开内核配置项 CONFIG_NO_HZ_IDLE,即可让系统在 Idle 前关闭周期 Tick,退出 Idle 时重新打开周期 Tick。
那么在关闭了周期 Tick 之后,系统何时被唤醒呢?
在关闭周期 Tick 时,同时会根据时钟子系统计算下一个时钟中断到来的时间,以这个时间为基准来设置一个 hrtimer 用于唤醒系统(高精度时钟框架),而这个时间的计算方法也很简单,即在所有注册到时钟框架的定时器中找到离此时最近的那一个的时间点作为这个时间。当然,用什么定时器来唤醒系统还要根据 CPU Idle 的深度来决定,后面会介绍。
不同层级的 CPU Idle 对唤醒时钟源的处理
前面提到了,系统关闭周期 Tick 的同时,会计算出下一个时钟中断到来的时间,以这个时间为基准来设置一个 hrtimer 用于唤醒系统。那么,如果有些 CPU 进入的层级比较深,关闭了 CPU 中的 hrtimer,系统将无法再次被唤醒。针对这种情况,则需要低功耗 Timer 去唤醒系统,这里先以 MTK 平台为例,在 CPU 进入 dpidle 和 soidle (两种 Idle 模式)时都会关闭 hrtimer ,另外起用一个 GPT Timer,而这个 GPT Timer 的超时时间直接从被关闭的 hrtimer 中的寄存器获取。这样就保证时间的延续性。因为 GPT Timer 是以 32K 晶振作为时钟源,所以在 CPU 进入 dpidle 时可以把 26M 的主时钟源给关闭,从而达到最大程度的省电。
以下我们通过源码探讨一下 MTK 的 CPU Idle 的实现,到底哪里设置 GPT Timer。其实很多平台为了实现 CPU 达到最省电的效果,都是使用这种做法。
MTK 的 CPU 一般有以下几种 Idle 模式
rgidle,浅度 Idle 模式,即 WFI
soidle,亮屏 Idle 模式
dpidle,灭屏 Idle 模式
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/22274.html