【原创】LinuxSuspend流程分析
背景
Read the fucking source code! --By 鲁迅
A picture is worth a thousand words. --By ⾼尔基
说明:
1. Kernel版本:4.14
2. ARM64处理器
3. 使⽤⼯具:Source Insight 3.5, Visio
1. 介绍
Linux Kernel⽀持四种Sleep State:
Suspend-to-Idle
纯软件,轻量级的Suspend操作,它会freeze user space,suspend the timekeeping,put all I/O devices into low-power states。
处于S2Idle状态下时,设备中断就可以将其唤醒。
Standby
除了实现Suspend-to-Idle时的操作外,还会将nonboot CPUs置于offline状态,以及suspend all low-level system functions。由于系统核⼼逻辑单元保持上电状态,操作的状态不会丢失,也会很容易恢复到之前的状态。
处于Standby状态时,可能需要依赖平台来设置唤醒源。
Suspend-to-RAM
STR/S2RAM时,除了Memory需要进⾏⾃刷新来保持数据外,其他的所有设备都需要进⼊到低功耗状态。除了实现Standby中的操作外,还有⼀些平台相关的操作要进⾏。⽐如,在STR的最后⼀步,将控制权交给Firmware,然后下电,等着唤醒时再重新Resume回来。由于存在掉电⾏为,因此Resume的时候需要重新进⾏配置。
处于STR状态时,需要依赖平台设置唤醒源。
本⽂主要分析的流程就是STR。
Hibernation
Suspend-to-Disk, STD,简⽽⾔之,这个操作会将运⾏时的context保存在Disk这种⾮易失的存储器中,然后进⾏掉电操作。当按下电源键进⾏唤醒时,Firmware/Uboot会将保存的context进⾏恢复。
上述四个状态,功耗节省效果依次增强,同时唤醒回来的时间开销也相应加⼤。
2. 流程
通过/sys接⼝可以触发Suspend流程:
cat /sys/power/state:查看⽀持的操作,⽐如:freeze, mem;
echo mem > /sys/power/state:进⾏STR操作;
echo freeze > /sys/power/state:进⾏S2Idle操作;
代码路径:
kernel/power/main.c
kernel/power/suspend.c
STR流程如下图,⼊⼝函数为pm_suspend:
简⽽⾔之,这是⼀张信息量很⼤的图⽚,涵盖了Suspend To Ram的整个流程。
linux下的sleep函数
图⽚中,从上到下涉及到进程的freeze,各种设备驱动的Suspend,平台的Suspend,CPU的Offline操作,syscore的Suspend操作。其中涉及到CPU 的操作时,在ARMv8中,会通过PSCI接⼝调⽤到ARM Trusted Firmware, ATF,这个在探讨过。
多说⽆益,看图吧。
3. process freeze
Suspend过程中,有⼀个函数suspend_freeze_processes引起了我的好奇⼼,我刻意分析了下。在Suspend的时候是需要将⽤户进程和内核线
程freeze掉,避免它们来捣乱,⽐如你在Suspend某个驱动的时候,此时⽤户还在使⽤该驱动的资源,这时候可能就会引起问题了。不过,内核线程并不是所有的都能freeze掉。
记住两个知识点:
⽤户线程的freeze是通过发送信号来触发执⾏的;
内核线程的freeze是通过主动调⽤函数触发的;
具体还是看图吧:
进程的操作⽐较复杂,以后在研究进程管理的时候再分析。