Static Power Management 用于设备处于 Inactive 状态时,消耗尽可能少的功率。即长时间不使用设备时,比如:手机息屏后待机场景。这种策略基于整个系统的全局低功耗状态,在这种状态下用户空间代码无法执行并且整个系统活动显著减少,称为睡眠状态。
当用户空间请求时,内核将系统置于这些状态之一,并且系统停留在其中,直到从指定设备之一接收到特殊信号(比如 Alarm 或 Modem 硬件中断),触发转换到用户空间代码可以运行的工作状态。因为睡眠状态是全局的,并且整个系统都会受到状态变化的影响,所以这种策略也被称为 system-wide power management (系统范围的电源管理)。
系统睡眠状态
根据其配置和运行平台的功能,Linux 内核可以支持多达四种系统睡眠状态,包括 hibernation (冬眠)和多达三种 system suspend(系统暂停)变体。下面列出了内核可以支持的睡眠状态:
-
Suspend-to-Idle ('freeze')
-
Power-on suspend ('standby')
-
Suspend-to-RAM ('mem')
-
Suspend-to-Disk ('disk')
在这几种状态中,设备睡眠程度越来越深,更加节省能源,也意味着睡眠和恢复的过程需要更长的时间以及消耗更多能源。
Android 设备仅支持 freeze 和 mem 两种状态。
Suspend-to-Idle('freeze')
这是一个通用的、纯软件的、轻量级的系统暂停(system suspend)(也被称为 S2I 或 S2Idle)的变体。
它通过下面的操作使处理器在系统暂停时可以在其最深的空闲状态下停滞更多的时间,从而相对于运行时空闲节省更多能源:
-
冻结用户空间
-
暂停计时
-
将所有I/O设备置于低功耗状态(可能比工作状态下的功耗更低)
该状态下系统可被带内中断唤醒(in-band interrupts),所以理论上任何能在工作状态下导致中断产生的设备也可以被设置为 S2Idle 的唤醒设备。
此状态可以在不支持 standby 或 Suspend-to-RAM 的平台上使用,也可以与任何更深层次的系统暂停变体一起使用,以减少恢复延迟(resume latency)。如果设置了 CONFIG_SUSPEND 内核配置选项,则始终支持它。
Power-on suspend ('standby')
这种状态,如果得到支持,可以提供适度但真实的能源节约,同时提供一个相对直接的过渡到工作状态。没有工作状态丢失(系统核心逻辑保留了电源),所以系统可以很容易地回到它离开的地方。它执行的操作包括:
-
冻结用户空间
-
暂停计时
-
将所有的I/O设备置于低功耗状态
-
非启动的CPU也会离线
-
所有的低级系统功能在过渡到这个状态时也会暂停
相对于 suspend-to-idle,它应该可以节省更多的能量,但是恢复的延迟通常会大。
Suspend-to-RAM ('mem')
这种状态(也被称为 STR 或 S2RAM)可以大大节省能源。因为系统中除了 memory(DDR)的所有东西,包括CPU,都进入了低功耗状态,通常都会断电。memory 进入自我刷新模式以保留其内容。
在进入 standby 状态时进行的所有步骤在过渡到 S2RAM 时也会进行。额外的操作可能会发生,这取决于平台的能力。特别是,在基于ACPI的系统中,内核在 S2RAM 转换过程中的最后一步将控制权交给平台固件(BIOS),这通常会导致关闭一些不受内核直接控制的低级组件。
Devices 和 CPU 的状态被保存并保留在内存中。所有设备都被暂停并进入低功耗状态。在许多情况下,所有外围总线在进入 S2RAM 时都会失去电源,因此设备必须能够处理返回 "on" 状态的过渡。
在基于 ACPI 的系统中,S2RAM 需要平台固件中的一些最小的启动限制代码,以便从它恢复系统。在其他平台上也可能是这样的情况。
相对于 suspend-to-idle 和 standby,能够从 S2RAM 唤醒系统的设备集通常会减少,可能有必要依靠平台来酌情设置唤醒功能。
如果设置了 CONFIG_SUSPEND 内核配置选项,并且平台在核心系统暂停子系统中注册了对它的支持,那么S2RAM就会得到支持。在基于 ACPI 的系统上,它被映射到 ACPI 定义的S3系统状态。
Android 使用 S2RAM 作为息屏待机时使用的休眠状态。
Suspend-to-Disk ('disk')
这种状态(也被称为 Hibernation(冬眠) 或 Suspend-to-Disk 或 STD)提供了最大的能源节约,即使在没有低级平台支持系统暂停的情况下也可以使用。然而,它需要一些用于恢复系统的底层 CPU 架构的低级代码。
Hibernation 相比于 S2RAM 明显的优势是 memory (DDR)也将断电,它与任何系统暂停的变体都有明显不同。它进入休眠状态需要三个系统状态变化,恢复则需要两个系统状态变化:
-
系统休眠时 :
-
首先,当休眠被触发时,内核会停止所有的系统活动,并创建一个内存的快照 image;
-
接下来,系统进入一个可以保存快照 image 的状态,image 被写入到持久性存储(EMMC or UFS)中;
-
最后系统进入目标低功耗状态,在这个状态下,除了有限的一组唤醒设备外,几乎所有的硬件组件,包括内存,都被切断电源。
一旦快照图像被写出来,系统可以进入一个特殊的低功耗状态(如ACPI S4),或者干脆自己断电。关机意味着最小的耗电,它使这种机制在任何系统上都能发挥作用。然而,进入特殊的低功耗状态可能允许使用额外的系统唤醒手段(例如按键盘上的一个键或打开笔记本电脑的盖子)。
-
系统恢复时:
-
唤醒后,控制权转到平台固件,该固件运行一个启动加载器,启动一个新的内核实例(控制权也可能直接转到启动加载器,这取决于系统配置,但无论如何,它都会导致一个新的内核实例被启动)。内核的新实例(被称为 restore kernel)在持久性存储中寻找 hibernation image ,如果找到了,就把它装入内存。
-
接下来,系统中的所有活动都被停止,还原内核用图像内容覆盖自己,并跳转到存储在 image 中的原始内核中的一个特殊蹦床区域(被称为 image kernel),这就是需要特殊架构的低级代码的地方。最后,图像内核将系统恢复到休眠前的状态,并允许用户空间再次运行。
如果设置了 CONFIG_HIBERNATION 内核配置选项,就支持 Hibernation 。然而,只有当对给定的CPU架构的支持包括系统恢复的低级代码时,才能设置这个选项。
系统暂停(System Suspend)和冬眠(Hibernation)的基本sysfs接口
电源管理子系统为用户空间提供了一个统一的sysfs接口,用于系统睡眠,而不受底层系统架构或平台的影响。该接口位于/sys/power/目录下(假设sysfs被挂载在/sys),它由以下属性(文件)组成:
state
这个文件包含一个字符串的列表,代表内核支持的睡眠状态。把这些字符串中的一个写进去,会使内核开始将系统转换到该字符串所代表的睡眠状态。
$cat /sys/power/state freeze standby mem disk
android 仅支持 freeze 和 mem。通常:
-
"freeze" 对应 Suspend-to-Idle
-
"standby" 对应 Standby(Power-on suspend)
-
"disk" 对应 Hibernation (Suspend-to-Disk )
而 "mem" 有多个变体,具体由文件 mem_sleep 的内容解释
mem_sleep
该文件包含一个代表支持的系统暂停变体的字符串列表,并允许用户空间选择与上述状态文件中的 "mem "字符串相关的变体。
$cat /sys/power/mem_sleep s2idle shallow [deep]
-
"s2idle" 代表 Suspend-to-idle
-
"shallow" 代表 Standby(Power-on suspend)
-
"deep" 代表 Suspend-to-RAM
在这个文件中写入一个列出的字符串会导致它所代表的系统暂停的变体与state文件中的 "mem "字符串相关联。代表当前与state文件中的 "mem "字符串相关联的暂停变量的字符串在方括号中显示。
根据上述可知,有两种方法可以使系统进入 Suspend-to-idle 状态:
-
直接向 /sys/power/state 写入 "freeze"
-
把 "s2idle" 写到 /sys/power/mem_sleep,然后把 "mem" 写到 /sys/power/state
同样,如果平台支持待机状态,也有两种方法可以使系统进入 Standby(Power-on suspend) 状态:
-
直接向 /sys/power/state 写入 "standby "
-
把 "shallow" 写到 /sys/power/mem_sleep,然后把 "mem" 写到 /sys/power/state
然而,只有一种方法可以使系统进入 Suspend-to-RAM 状态:
-
"deep" 写入 /sys/power/mem_sleep,"mem" 写入 /sys/power/state
disk
这个文件控制 hibernation(Suspend-to-Disk)的操作模式。具体来说,它告诉内核在创建 hibernation image 后要做什么。
$cat /sys/power/disk
platform [shutdown] reboot suspend test_resume
- platform
将系统放入一个特殊的低功耗状态(例如ACPI S4),以使更多的唤醒选项可用,并可能允许平台固件在唤醒后采取简化的初始化路径。
只有在平台提供特殊机制,在创建 hibernation image 后使系统进入休眠状态时,它才可用(例如,具有ACPI的平台通常会这样做)。
- shutdown
关闭系统电源。
- reboot
重新启动系统(主要对诊断有用)。
- suspend
混合系统挂起。让系统进入通过上述 mem_sleep 文件选择的暂停睡眠状态。如果系统成功地从该状态下被唤醒,丢弃休眠镜像并继续。否则,使用该映像来恢复系统的先前状态。
如果支持系统挂起,它就可用。可作为 S2RAM 状态增强稳定性的缓解措施,用于解决 DDR 不稳定,其他子系统 panic 或者断电等异常使得机器无法从 S2RAM 正常恢复到休眠前的状态。
- test_resume
诊断操作。加载镜像,就像系统刚刚从 hibernation 中醒来,当前运行的内核实例是一个 restore kernel,然后跟进全系统恢复。
将上面列出的一个字符串写进这个文件,会使它所代表的选项被选中。
当前选择的选项显示在方括号中,这意味着当 hibernation 被触发时,通过向/sys/power/state写入 "disk",它所代表的操作将在创建和保存镜像之后进行。
image_size
这个文件控制 hibernation images 的大小。
从中读取返回当前的 image 大小限制,默认情况下,它被设置为可用RAM大小的2/5左右。
pm_trace
这个文件控制着 "PM跟踪" 机制,在RTC内存中保存最后一个暂停或恢复的事件点,跨越重启。它有助于更有效地调试在系统挂起或恢复过程中发生的设备驱动程序故障导致的硬锁定或重启(这种情况更常见)。
如果它包含 "1",每个暂停/恢复事件点的指纹将依次存储在RTC存储器中(覆盖实际的RTC信息),因此,如果系统崩溃在存储后立即发生,它将幸存下来,并且可以在以后用来识别导致崩溃发生的驱动程序。
它默认包含 "0",可以通过写一个代表非零整数的字符串来改变为 "1"。
参考
[1]. System Sleep States