系统睡眠状态

版权:

© 2017 英特尔公司

作者:

Rafael J. Wysocki <rafael.j.wysocki@intel.com>

睡眠状态是整个系统的全局低功耗状态,在这些状态下,用户空间代码无法执行,并且整体系统活动显著减少。

可以支持的睡眠状态

根据其配置及其运行平台的性能,Linux 内核最多可以支持四种系统睡眠状态,包括休眠和最多三种系统挂起变体。内核可以支持的睡眠状态如下所示。

挂起到空闲

这是系统挂起的一种通用、纯软件、轻量级变体(也称为 S2I 或 S2Idle)。它通过冻结用户空间、暂停计时并将所有 I/O 设备置于低功耗状态(可能比工作状态中的可用功耗更低)来节省更多能量,这样处理器可以在系统挂起时在最深的空闲状态中花费时间。

系统通过带内中断从此状态唤醒,因此理论上任何可以在工作状态下导致生成中断的设备也可以设置为 S2Idle 的唤醒设备。

此状态可以在不支持 待机挂起到 RAM 的平台上使用,或者可以与任何更深的系统挂起变体一起使用,以提供减少的恢复延迟。如果设置了 CONFIG_SUSPEND 内核配置选项,则始终支持它。

待机

如果支持此状态,则它提供适度但实际的节能效果,同时提供相对简单的返回工作状态的过渡。不会丢失任何操作状态(系统核心逻辑保持通电),因此系统可以轻松返回到离开的位置。

除了冻结用户空间、暂停计时并将所有 I/O 设备置于低功耗状态(这也是为 挂起到空闲 执行的操作)之外,非引导 CPU 将脱机,并且所有低级系统功能在过渡到此状态期间都会被暂停。因此,它应该比 挂起到空闲 节省更多能量,但恢复延迟通常会比该状态更长。

可以从此状态唤醒系统的设备集通常相对于 挂起到空闲 减少,并且可能需要依赖平台来根据需要设置唤醒功能。

如果设置了 CONFIG_SUSPEND 内核配置选项,并且平台通过核心系统挂起子系统注册了对其的支持,则支持此状态。在基于 ACPI 的系统上,此状态映射到 ACPI 定义的 S1 系统状态。

挂起到 RAM

如果支持此状态(也称为 STR 或 S2RAM),则它可以提供显著的节能效果,因为系统中的所有内容都置于低功耗状态,除了内存,内存应置于自刷新模式以保留其内容。在进入 待机 时执行的所有步骤也会在过渡到 S2RAM 期间执行。根据平台功能,可能会执行其他操作。特别是,在基于 ACPI 的系统上,内核在 S2RAM 过渡期间作为最后一步将控制权传递给平台固件 (BIOS),这通常会导致关闭一些不由内核直接控制的更多低级组件。

设备和 CPU 的状态会保存并保存在内存中。所有设备都会被挂起并置于低功耗状态。在许多情况下,进入 S2RAM 时,所有外围总线都会断电,因此设备必须能够处理返回“开”状态的过渡。

在基于 ACPI 的系统上,S2RAM 需要平台固件中一些最少的引导代码,以从中恢复系统。其他平台上也可能出现这种情况。

可以从 S2RAM 唤醒系统的设备集通常相对于 挂起到空闲待机 减少,并且可能需要依赖平台来根据需要设置唤醒功能。

如果设置了 CONFIG_SUSPEND 内核配置选项,并且平台通过核心系统挂起子系统注册了对其的支持,则支持 S2RAM。在基于 ACPI 的系统上,它映射到 ACPI 定义的 S3 系统状态。

休眠

此状态(也称为挂起到磁盘或 STD)提供最大的节能效果,即使在没有对系统挂起的低级平台支持的情况下也可以使用。但是,它需要一些低级代码才能恢复底层 CPU 架构的系统。

休眠与任何系统挂起变体都有很大不同。它需要三个系统状态更改才能使其进入休眠状态,并且需要两个系统状态更改才能恢复它。

首先,当触发休眠时,内核会停止所有系统活动并创建一个要写入持久性存储器的内存快照映像。接下来,系统进入可以保存快照映像的状态,写入映像,最后,系统进入目标低功耗状态,在该状态下,几乎所有硬件组件(包括内存)都断电,除了一组有限的唤醒设备。

一旦写入快照映像,系统可能会进入特殊的低功耗状态(如 ACPI S4),或者可能会直接关闭自身。关闭电源意味着最小的功耗,它允许此机制在任何系统上工作。但是,进入特殊的低功耗状态可能会允许使用其他系统唤醒方式(例如,按键盘上的键或打开笔记本电脑的盖子)。

唤醒后,控制权将转到运行引导加载程序的平台固件,该引导加载程序会引导内核的新实例(控制权也可能直接转到引导加载程序,具体取决于系统配置,但无论如何都会导致引导内核的新实例)。内核的新实例(称为restore kernel)在持久性存储中查找休眠映像,如果找到,则将其加载到内存中。接下来,停止系统中的所有活动,并且恢复内核用映像内容覆盖自身并跳转到存储在映像中的原始内核中的特殊蹦床区域(称为image kernel),这是需要特殊的特定于体系结构的低级代码的地方。最后,映像内核将系统还原到休眠前的状态,并允许用户空间再次运行。

如果设置了 CONFIG_HIBERNATION 内核配置选项,则支持休眠。但是,只有当给定 CPU 体系结构的支持包括用于系统恢复的低级代码时,才能设置此选项。

系统挂起和休眠的基本 sysfs 接口

电源管理子系统为用户空间提供了一个统一的 sysfs 接口,用于系统睡眠,而无需考虑底层系统架构或平台。该接口位于 /sys/power/ 目录(假设 sysfs 挂载在 /sys ),它由以下属性(文件)组成:

state

此文件包含一个字符串列表,表示内核支持的睡眠状态。向其中写入这些字符串之一会导致内核开始将系统转换为该字符串表示的睡眠状态。

特别是,“disk”、“freeze”和“standby”字符串分别代表休眠挂起到空闲待机睡眠状态。“mem”字符串的解释取决于下面描述的 mem_sleep 文件的内容。

如果内核不支持任何系统睡眠状态,则此文件不存在。

mem_sleep

此文件包含一个字符串列表,表示支持的系统挂起变体,并允许用户空间选择与上述 state 文件中的“mem”字符串关联的变体。

此文件中可能存在的字符串是“s2idle”、“shallow”和“deep”。“s2idle”字符串始终代表挂起到空闲,并且按照惯例,“shallow”和“deep”分别代表待机挂起到RAM

向此文件写入列出的字符串之一会导致该字符串表示的系统挂起变体与 state 文件中的“mem”字符串关联。表示当前与 state 文件中的“mem”字符串关联的挂起变体的字符串显示在方括号中。

如果内核不支持系统挂起,则此文件不存在。

disk

此文件控制休眠(挂起到磁盘)的操作模式。具体来说,它告诉内核在创建休眠映像后该做什么。

从中读取会返回一个编码为支持选项的列表:

platform

将系统置于特殊的低功耗状态(例如 ACPI S4),以使其他唤醒选项可用,并可能允许平台固件在唤醒后采用简化的初始化路径。

仅当平台提供特殊机制以在创建休眠映像后使系统进入睡眠状态时才可用(通常具有 ACPI 的平台会这样做,例如)。

shutdown

关闭系统电源。

reboot

重启系统(主要用于诊断)。

suspend

混合系统挂起。使系统进入通过上述 mem_sleep 文件选择的挂起睡眠状态。如果系统成功从该状态唤醒,则丢弃休眠映像并继续。否则,使用该映像恢复系统之前的状态。

如果支持系统挂起,则此项可用。

test_resume

诊断操作。加载映像,就像系统刚从休眠中唤醒,并且当前正在运行的内核实例是恢复内核,然后进行完整的系统恢复。

向此文件写入上面列出的字符串之一会导致选择该字符串表示的选项。

当前选择的选项显示在方括号中,这意味着当通过将 disk 写入 /sys/power/state 来触发休眠时,将在创建并保存映像后执行由该选项表示的操作。

如果内核不支持休眠,则此文件不存在。

image_size

此文件控制休眠映像的大小。

可以写入一个表示非负整数的字符串,该整数将用作映像大小的最佳上限(以字节为单位)。休眠核心将尽力确保映像大小不超过该数字,但是如果无法实现,仍将创建休眠映像,并且其大小将尽可能小。特别是,向此文件写入“0”会导致休眠映像的大小最小。

从中读取会返回当前的映像大小限制,默认情况下设置为可用 RAM 大约 2/5。

pm_trace

此文件控制“PM 跟踪”机制,该机制在重启时将上次挂起或恢复事件点保存在 RTC 内存中。它有助于更有效地调试在系统挂起或恢复期间(这种情况更常见)由于设备驱动程序故障而导致的硬锁定或重启。

如果它包含“1”,则每个挂起/恢复事件点的指纹将依次存储在 RTC 内存中(覆盖实际的 RTC 信息),因此如果系统在存储后立即崩溃,它将仍然存在,并且可以稍后用于识别导致崩溃发生的驱动程序。

默认情况下,它包含“0”,可以通过向其中写入表示非零整数的字符串将其更改为“1”。

根据以上所述,有两种方法使系统进入挂起到空闲状态。第一种方法是直接将“freeze”写入 /sys/power/state。第二种方法是将“s2idle”写入 /sys/power/mem_sleep,然后将“mem”写入 /sys/power/state。同样,如果有平台支持待机状态,则有两种方法使系统进入该状态(在这种情况下,要写入控制文件的字符串分别是“standby”或“shallow”和“mem”)。但是,只有一种方法使系统进入挂起到RAM状态(将“deep”写入 /sys/power/mem_sleep,并将“mem”写入 /sys/power/state)。

默认的挂起变体(即不向 /sys/power/mem_sleep 写入任何内容时使用的变体)是“deep”(在大多数支持挂起到RAM的系统上)或“s2idle”,但它可以通过内核命令行中的 mem_sleep_default 参数的值覆盖。在某些具有 ACPI 的系统上,根据 ACPI 表中的信息,即使原则上支持挂起到RAM,默认值也可能是“s2idle”。