尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Linux 系统睡眠状态(System Sleep States)完全指南:s2idle、Standby、S2RAM 与 Hibernation 的机制与 /sys/power 操作

Linux 系统睡眠状态(System Sleep States)完全指南:s2idle、Standby、S2RAM 与 Hibernation 的机制与 /sys/power 操作 Linux 系统睡眠状态System Sleep States完全指南s2idle、Standby、S2RAM 与 Hibernation 的机制与 /sys/power 操作【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux本文基于 Linux 内核官方文档 sleep-states.rst 及内核电源管理子系统源码系统讲解 Linux 支持的四种全局系统睡眠状态Suspend-to-Idle、Standby、Suspend-to-RAM、Hibernation的底层机制、适用场景以及通过/sys/power/下state、mem_sleep、disk、image_size、pm_trace等接口触发和管理睡眠/休眠的完整方法。读完本文你将理解各睡眠状态的节能程度、唤醒方式与唤醒延迟差异并能熟练地在任意 Linux 系统上通过 sysfs 与内核命令行参数精确控制睡眠行为。什么是系统睡眠状态系统睡眠状态System Sleep States是覆盖整个系统的全局低功耗状态。进入该状态后用户空间代码无法执行系统整体活动显著降低。睡眠状态由内核统一管理其支持情况取决于内核配置CONFIG_SUSPEND、CONFIG_HIBERNATION等以及所在平台尤其是 ACPI 平台的能力。Linux 内核最多可以支持四种系统睡眠状态休眠Hibernation即 Suspend-to-Disk加三种系统挂起system suspend变体。它们之间的核心差异体现在三个方面能量节省程度、恢复延迟与唤醒设备集合。从源码结构看这些状态由 kernel/power/suspend.c 中的标签枚举统一管理const char * const pm_labels[] { [PM_SUSPEND_TO_IDLE] freeze, [PM_SUSPEND_STANDBY] standby, [PM_SUSPEND_MEM] mem, }; const char * const mem_sleep_labels[] { [PM_SUSPEND_TO_IDLE] s2idle, [PM_SUSPEND_STANDBY] shallow, [PM_SUSPEND_MEM] deep, };pm_labels是写入/sys/power/state的字符串mem_sleep_labels是写入/sys/power/mem_sleep的字符串两者的对应关系在后续章节详细说明。四种睡眠状态详解Suspend-to-Idles2idle纯软件轻量挂起Suspend-to-Idle简称 S2I 或 S2Idle是一种通用的、纯软件实现的轻量级系统挂起变体。与运行时空闲runtime idle相比它能节省更多能量内核会冻结用户空间、挂起时间管理timekeeping并将所有 I/O 设备置于低功耗状态可能比工作状态下的功耗更低从而使处理器在系统挂起期间能够进入其最深度的空闲状态。S2Idle 的特点唤醒方式系统通过带内中断in-band interrupts唤醒。理论上任何能在工作状态下产生中断的设备都可以被设置为 S2Idle 的唤醒设备因此它的唤醒设备集合最广。适用场景可以在不支持 Standby 或 Suspend-to-RAM 的平台上使用也可以与更深度的系统挂起变体配合使用以提供更低的恢复延迟即作为低延迟备选。支持条件只要设置了CONFIG_SUSPEND内核配置选项S2Idle 就始终受支持。在源码中S2Idle 的特殊地位体现在 kernel/power/suspend.c 的pm_states_init()即使平台没有注册任何suspend_opsmem 和 freeze 也总是出现在/sys/power/state中且mem_sleep_states[PM_SUSPEND_TO_IDLE]无条件初始化为 s2idlevoid __init pm_states_init(void) { /* mem and freeze are always present in /sys/power/state. */ pm_states[PM_SUSPEND_MEM] pm_labels[PM_SUSPEND_MEM]; pm_states[PM_SUSPEND_TO_IDLE] pm_labels[PM_SUSPEND_TO_IDLE]; /* * Suspend-to-idle should be supported even without any suspend_ops, * initialize mem_sleep_states[] accordingly here. */ mem_sleep_states[PM_SUSPEND_TO_IDLE] mem_sleep_labels[PM_SUSPEND_TO_IDLE]; }进入 S2Idle 的核心路径在s2idle_enter()kernel/power/suspend.c在确认没有 pending 的唤醒事件后内核通过wake_up_all_idle_cpus()将所有 CPU 推入空闲循环当前 CPU 则通过swait_event_exclusive()等待唤醒事件直到s2idle_state变为S2IDLE_STATE_WAKE。Standby中等节能、易于恢复Standby对应 ACPI S1如果受支持能提供中等但真实的能量节省同时从该状态恢复到工作状态的路径相对简单直接。系统核心逻辑仍保持供电因此不会丢失任何运行状态系统可以轻松地回到中断前的状态。与 S2Idle 相比进入 Standby 除了同样冻结用户空间、挂起时间管理、将所有 I/O 设备置于低功耗状态外还会将非引导 CPUnonboot CPUs下线taken offline挂起所有底层系统功能all low-level system functions are suspended。因此 Standby 通常比 S2Idle 更节能但恢复延迟一般也更大。其唤醒设备集合通常比 S2Idle 更小可能需要依赖平台来配置唤醒功能。支持条件设置CONFIG_SUSPEND且平台向核心系统挂起子系统注册了 Standby 支持。在 ACPI 系统中Standby 映射到 ACPI 定义的 S1 状态。从源码看Standby 和 S2RAM 的注册依赖于平台调用suspend_set_ops()kernel/power/suspend.c只有平台 ops 的valid()回调认可该状态时对应的标签才会被填充进mem_sleep_states[]和pm_states[]进而出现在 sysfs 中void suspend_set_ops(const struct platform_suspend_ops *ops) { ... suspend_ops ops; if (valid_state(PM_SUSPEND_STANDBY)) { mem_sleep_states[PM_SUSPEND_STANDBY] mem_sleep_labels[PM_SUSPEND_STANDBY]; pm_states[PM_SUSPEND_STANDBY] pm_labels[PM_SUSPEND_STANDBY]; if (mem_sleep_default PM_SUSPEND_STANDBY) mem_sleep_current PM_SUSPEND_STANDBY; } if (valid_state(PM_SUSPEND_MEM)) { mem_sleep_states[PM_SUSPEND_MEM] mem_sleep_labels[PM_SUSPEND_MEM]; if (mem_sleep_default PM_SUSPEND_MEM) mem_sleep_current PM_SUSPEND_MEM; } ... }注意mem_sleep_current的初始值是PM_SUSPEND_TO_IDLEkernel/power/suspend.c如果平台支持 S2RAM 且未指定其他默认值suspend_set_ops()会把它切换为PM_SUSPEND_MEM这与文档所述大多数支持 S2RAM 的系统默认挂起变体为 deep一致。Suspend-to-RAMS2RAM/STR内存自刷新深度节能Suspend-to-RAM简称 STR 或 S2RAM对应 ACPI S3如果受支持能提供显著的节能效果系统中除内存外的一切都被置于低功耗状态而内存必须进入**自刷新模式self-refresh mode**以保持其内容。进入 S2RAM 会执行进入 Standby 的全部步骤并根据平台能力执行额外操作。特别地在 ACPI 系统中内核在 S2RAM 转换的最后一步将控制权交给平台固件BIOS这通常会关闭更多内核无法直接控制的底层组件。S2RAM 的关键特征状态保存设备和 CPU 的状态被保存并保持在内存中所有设备被挂起并进入低功耗状态。在许多情况下进入 S2RAM 时所有外设总线都会断电因此设备必须能够处理回到开启状态的转换。固件要求在 ACPI 系统中S2RAM 需要平台固件中存在一些最小的引导代码boot-strapping code来从该状态恢复系统其他平台也可能有类似要求。唤醒设备能从 S2RAM 唤醒系统的设备集合通常比 S2Idle 和 Standby 更小且可能必须依赖平台来设置唤醒功能。支持条件设置CONFIG_SUSPEND且平台注册了支持。在 ACPI 系统中映射到 ACPI S3 状态。CONFIG_SUSPEND选项的定义见 kernel/power/Kconfigconfig SUSPEND bool Suspend to RAM and standby depends on ARCH_SUSPEND_POSSIBLE default y help Allow the system to enter sleep states in which main memory is powered and thus its contents are preserved, such as the suspend-to-RAM state (e.g. the ACPI S3 state).HibernationSuspend-to-Disk最大节能断电级别Hibernation也称 Suspend-to-Disk 或 STD提供最大的能量节省并且可以在完全没有底层平台挂起支持的情况下使用但它要求底层 CPU 架构具备用于恢复系统的低级代码。其CONFIG_HIBERNATION配置选项见 kernel/power/Kconfig依赖SWAP ARCH_HIBERNATION_POSSIBLE。Hibernation 与三种系统挂起变体有本质不同进入休眠需要三次系统状态转换恢复则需要两次。进入休眠的三阶段流程创建快照触发休眠时内核停止所有系统活动创建内存的快照镜像snapshot image准备写入持久存储写出镜像系统进入可以保存快照镜像的状态将镜像写出例如写入 swap 分区进入目标低功耗状态系统进入目标低功耗状态此时几乎所有硬件组件包括内存都被切断电源仅保留有限的一组唤醒设备。镜像写出后系统有两种去向进入特殊低功耗状态如 ACPI S4可以获得额外的唤醒手段例如按键盘按键或打开笔记本盖子唤醒直接断电shutdown功耗最小且该机制可在任何系统上工作。恢复的两阶段流程唤醒后控制权交给平台固件固件运行引导加载程序boot loader后者启动一个全新的内核实例称为restore kernel。该实例在持久存储中查找休眠镜像找到后将其加载进内存系统停止所有活动restore kernel 用镜像内容覆盖自身然后跳转到镜像中原始内核称为image kernel的一个特殊蹦床区域trampoline area——这正是需要架构相关低级代码的地方。最后image kernel 将系统恢复到休眠前的状态允许用户空间再次运行。Hibernation 的支持条件是设置CONFIG_HIBERNATION且该选项仅在给定 CPU 架构包含系统恢复的低级代码时才能设置。内核还要求镜像能写入持久存储因此CONFIG_HIBERNATION依赖SWAP见 kernel/power/Kconfig。/sys/power 下的 sysfs 接口电源管理子系统为系统睡眠提供了与底层架构/平台无关的统一 sysfs 接口位于/sys/power/目录假设 sysfs 挂载在/sys。所有属性的实现集中在 kernel/power/main.c 中。以下是各属性文件的完整说明。state触发睡眠状态转换state文件包含内核支持的睡眠状态字符串列表。向其中写入某个字符串内核就会开始向该字符串代表的睡眠状态转换。disk代表 Hibernationfreeze代表 Suspend-to-Idlestandby代表 Standbymem的解读取决于mem_sleep文件的内容见下节。如果内核不支持任何系统睡眠状态该文件不会出现。从源码看state_show()kernel/power/main.c会遍历pm_states[]输出所有已注册的挂起状态字符串并在末尾追加disk若hibernation_available()state_store()与decode_state()kernel/power/main.c实现了写入逻辑其中关键的一点是写入mem时会被替换为mem_sleep_current所代表的状态state decode_state(buf, n); if (state PM_SUSPEND_MAX) { if (state PM_SUSPEND_MEM) state mem_sleep_current; error pm_suspend(state); } else if (state PM_SUSPEND_MAX) { error hibernate(); /* disk 映射到 hibernate() */ }mem_sleep为 mem 选择挂起变体mem_sleep文件列出受支持的系统挂起变体允许用户空间选择与state文件中mem字符串关联的变体。可能出现的字符串为s2idle、shallow和deep按约定s2idle总是代表 Suspend-to-Idleshallow代表 Standbydeep代表 Suspend-to-RAM写入其中一个字符串会使它所代表的挂起变体与state文件中的mem关联读取时当前与mem关联的变体字符串显示在方括号中例如s2idle [deep]。如果内核不支持系统挂起该文件不会出现。在源码中mem_sleep_currentkernel/power/suspend.c就是当前与mem关联的变体初始为PM_SUSPEND_TO_IDLE可被suspend_set_ops()或写入mem_sleep文件改变。disk控制休眠的运作模式disk文件控制 Hibernation 的运作模式即告诉内核创建休眠镜像之后做什么。读取该文件返回受支持的选项列表写入其中一个字符串即选中对应选项当前选中的选项显示在方括号中即触发休眠时向state写入disk将执行的操作。支持的选项选项含义platform创建镜像后将系统放入特殊低功耗状态如 ACPI S4以获得额外唤醒手段并可能让平台固件在唤醒后走简化的初始化路径。仅当平台提供创建镜像后入睡的特殊机制时才可用ACPI 平台通常如此。shutdown断电关闭系统。reboot重启系统主要用于诊断。suspend混合系统挂起Hybrid suspend将系统放入通过mem_sleep文件选定的挂起状态。若系统从该状态成功唤醒则丢弃休眠镜像继续运行否则使用镜像恢复系统先前状态。系统挂起受支持时即可用。test_resume诊断操作仿佛系统刚从休眠中唤醒且当前内核是 restore kernel加载镜像并执行完整的系统恢复。如果内核不支持休眠该文件不会出现。源码中这些模式定义在 kernel/power/hibernate.c默认模式是HIBERNATION_SHUTDOWNenum { HIBERNATION_PLATFORM, HIBERNATION_SHUTDOWN, HIBERNATION_REBOOT, HIBERNATION_SUSPEND, HIBERNATION_TEST_RESUME, }; static int hibernation_mode HIBERNATION_SHUTDOWN;对应的用户可见字符串在 kernel/power/hibernate.c[HIBERNATION_PLATFORM] platform, [HIBERNATION_SHUTDOWN] shutdown, [HIBERNATION_REBOOT] reboot, [HIBERNATION_SUSPEND] suspend, [HIBERNATION_TEST_RESUME] test_resume,注意当平台注册了休眠 ops 时hibernation_set_ops()kernel/power/hibernate.c若当前模式是HIBERNATION_PLATFORM而平台不再支持会自动回退为HIBERNATION_SHUTDOWN反之若平台支持且当前模式为HIBERNATION_PLATFORM会保持。image_size控制休眠镜像大小image_size文件控制休眠镜像的大小写入一个表示非负整数的字符串作为镜像大小的尽力而为上限best-effort upper limit单位为字节。休眠核心会尽力确保镜像大小不超过该数值如果实在无法达到仍会创建镜像且大小尽可能小。特别地写入0会使休眠镜像大小最小化读取返回当前的镜像大小上限默认约为可用 RAM 大小的 2/5。pm_trace跨重启保存挂起/恢复事件指纹pm_trace文件控制 PM trace 机制将最后一次挂起或恢复事件点event point保存在 RTC 内存中使其在重启后仍然存活。这有助于更有效地调试由设备驱动故障引起的、发生在系统挂起或恢复期间恢复期间更常见的硬锁死或重启问题。若文件内容为1每个挂起/恢复事件点的指纹会依次存入 RTC 内存覆盖实际的 RTC 信息因此如果存储后立即发生系统崩溃该指纹可以存活之后用于识别导致崩溃的驱动程序默认内容为0可以通过写入一个表示非零整数的字符串改为1。实际操作如何触发各睡眠状态根据文档与state_store()的实现触发各睡眠状态的方法如下目标状态方法一方法二Suspend-to-Idleecho freeze /sys/power/stateecho s2idle /sys/power/mem_sleep后再echo mem /sys/power/stateStandbyecho standby /sys/power/stateecho shallow /sys/power/mem_sleep后再echo mem /sys/power/state平台支持时Suspend-to-RAM仅有一种方式echo deep /sys/power/mem_sleep后再echo mem /sys/power/stateHibernationecho disk /sys/power/state配合disk文件选择模式—也就是说freeze、standby可以直接写入state而mem是一个间接字符串实际进入哪个挂起变体由mem_sleep文件中的选择即mem_sleep_current决定。Hibernation 则只能通过向state写入disk触发具体行为shutdown/reboot/platform/suspend/test_resume由disk文件的当前选择决定。默认挂起变体与 mem_sleep_default 内核参数默认挂起变体即不写入/sys/power/mem_sleep时使用的变体通常是deep在大多数支持 Suspend-to-RAM 的系统上或s2idle但可以通过内核命令行参数mem_sleep_default覆盖。在某些 ACPI 系统上根据 ACPI 表信息即使原则上支持 Suspend-to-RAM默认也可能是s2idle。该参数的解析实现在 kernel/power/suspend.cstatic int __init mem_sleep_default_setup(char *str) { suspend_state_t state; for (state PM_SUSPEND_TO_IDLE; state PM_SUSPEND_MEM; state) if (mem_sleep_labels[state] !strcmp(str, mem_sleep_labels[state])) { mem_sleep_default state; mem_sleep_current state; break; } return 1; } __setup(mem_sleep_default, mem_sleep_default_setup);用法示例在引导加载程序的 kernel 命令行中加入mem_sleep_defaultdeep、mem_sleep_defaults2idle或mem_sleep_defaultshallow即可将对应变体设为默认。注意该参数只接受mem_sleep_labels[]中的字符串s2idle/shallow/deep并且在平台注册suspend_set_ops()时mem_sleep_default会影响mem_sleep_current的最终取值见上文suspend_set_ops()源码。源码视角的挂起/恢复主流程对于系统挂起s2idle/standby/S2RAM 共用核心入口是enter_state()kernel/power/suspend.c与suspend_devices_and_enter()kernel/power/suspend.c。其大致流程为获取system_transition_mutex互斥锁防止并发睡眠转换若启用sync_on_suspend_enabled先执行文件系统同步pm_sleep_fs_sync()冻结用户进程suspend_prepare()挂起控制台console_suspend_all()按设备模型顺序挂起所有设备dpm_suspend_start()进入睡眠循环suspend_enter()若被假唤醒!wakeup且平台要求重试platform_suspend_again()则重复恢复设备dpm_resume_end()、恢复控制台最后解冻进程并唤醒文件系统suspend_finish()。其中 S2Idle 走s2idle_ops回调链prepare_late、wake、restore_early、restore等见 kernel/power/suspend.c而 Standby/S2RAM 走suspend_ops平台回调链。valid_state()kernel/power/suspend.c要求平台 ops 提供valid()且enter()回调才认为状态有效。对于休眠主流程在 kernel/power/hibernate.c 的hibernate()与hibernation_snapshot()/create_image()中前者负责冻结进程、挂起设备dpm_suspend(PMSG_FREEZE)、调用create_image()创建镜像期间执行syscore_suspend()与架构相关的swsusp_arch_suspend()写盘后按hibernation_mode执行 shutdown/reboot/platform/suspend 等动作恢复时则由 restore kernel 走swsusp_resume()路径最终跳入镜像中的 trampoline。配置开关与延伸阅读与本文主题直接相关的内核配置项均位于 kernel/power/KconfigCONFIG_SUSPEND启用 Suspend to RAM 与 standby依赖ARCH_SUSPEND_POSSIBLE默认 yCONFIG_SUSPEND_FREEZER挂起前的任务冻结器默认 y不推荐关闭CONFIG_SUSPEND_SKIP_SYNC跳过挂起前的内核sys_sync()运行时可通过/sys/power/sync_on_suspend切换CONFIG_HIBERNATION启用休眠依赖SWAP ARCH_HIBERNATION_POSSIBLE自动选择 LZO/LZ4 压缩算法。如需深入了解挂起/恢复的设备流程细节可继续阅读仓库内的 suspend-flows.rst系统级电源管理各主题的索引见 system-wide.rst 与 index.rst。小结Linux 系统睡眠状态是一个节能程度与恢复延迟/复杂度的权衡体系Suspend-to-Idle 纯软件、兼容性最好、唤醒最快Standby 与 Suspend-to-RAM 依赖平台注册分别对应 ACPI S1 与 S3S2RAM 凭借内存自刷新实现深度节能Hibernation 通过内存快照落盘实现断电级节能且不依赖平台挂起支持。日常使用中掌握/sys/power/state、/sys/power/mem_sleep、/sys/power/disk三个核心文件以及mem_sleep_default内核参数即可在几乎所有 Linux 系统上精确、可控地管理挂起与休眠行为。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表