news 2026/9/11 20:59:30

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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/statemem_sleepdiskimage_sizepm_trace等接口触发和管理睡眠/休眠的完整方法。读完本文,你将理解各睡眠状态的节能程度、唤醒方式与唤醒延迟差异,并能熟练地在任意 Linux 系统上通过 sysfs 与内核命令行参数精确控制睡眠行为。

什么是系统睡眠状态

系统睡眠状态(System Sleep States)是覆盖整个系统的全局低功耗状态。进入该状态后,用户空间代码无法执行,系统整体活动显著降低。睡眠状态由内核统一管理,其支持情况取决于内核配置(CONFIG_SUSPENDCONFIG_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-Idle(s2idle):纯软件轻量挂起

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_ops,"mem" 和 "freeze" 也总是出现在/sys/power/state中,且mem_sleep_states[PM_SUSPEND_TO_IDLE]无条件初始化为 "s2idle":

void __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 设备置于低功耗状态外,还会:

  • 将非引导 CPU(nonboot 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_IDLE(kernel/power/suspend.c),如果平台支持 S2RAM 且未指定其他默认值,suspend_set_ops()会把它切换为PM_SUSPEND_MEM,这与文档所述"大多数支持 S2RAM 的系统默认挂起变体为 deep"一致。

Suspend-to-RAM(S2RAM/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/Kconfig:

config 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).

Hibernation(Suspend-to-Disk):最大节能,断电级别

Hibernation(也称 Suspend-to-Disk 或 STD)提供最大的能量节省,并且可以在完全没有底层平台挂起支持的情况下使用;但它要求底层 CPU 架构具备用于恢复系统的低级代码。其CONFIG_HIBERNATION配置选项见 kernel/power/Kconfig,依赖SWAP && ARCH_HIBERNATION_POSSIBLE

Hibernation 与三种系统挂起变体有本质不同:进入休眠需要三次系统状态转换,恢复则需要两次

进入休眠的三阶段流程

  1. 创建快照:触发休眠时,内核停止所有系统活动,创建内存的快照镜像(snapshot image),准备写入持久存储;
  2. 写出镜像:系统进入可以保存快照镜像的状态,将镜像写出(例如写入 swap 分区);
  3. 进入目标低功耗状态:系统进入目标低功耗状态,此时几乎所有硬件组件(包括内存)都被切断电源,仅保留有限的一组唤醒设备。

镜像写出后,系统有两种去向:

  • 进入特殊低功耗状态(如 ACPI S4):可以获得额外的唤醒手段(例如按键盘按键或打开笔记本盖子唤醒);
  • 直接断电(shutdown):功耗最小,且该机制可在任何系统上工作。

恢复的两阶段流程

  1. 唤醒后,控制权交给平台固件,固件运行引导加载程序(boot loader),后者启动一个全新的内核实例(称为restore kernel)。该实例在持久存储中查找休眠镜像,找到后将其加载进内存;
  2. 系统停止所有活动,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"代表 Hibernation;
  • "freeze"代表 Suspend-to-Idle;
  • "standby"代表 Standby;
  • "mem"的解读取决于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-Idle,"shallow"代表 Standby,"deep"代表 Suspend-to-RAM;
  • 写入其中一个字符串,会使它所代表的挂起变体与state文件中的"mem"关联;
  • 读取时,当前与"mem"关联的变体字符串显示在方括号中,例如s2idle [deep]

如果内核不支持系统挂起,该文件不会出现。在源码中,mem_sleep_current(kernel/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_SHUTDOWN

enum { 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/state
Standbyecho 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/state
Hibernationecho 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.c:

static 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_default=deepmem_sleep_default=s2idlemem_sleep_default=shallow,即可将对应变体设为默认。注意该参数只接受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)。其大致流程为:

  1. 获取system_transition_mutex互斥锁,防止并发睡眠转换;
  2. 若启用sync_on_suspend_enabled,先执行文件系统同步(pm_sleep_fs_sync());
  3. 冻结用户进程(suspend_prepare());
  4. 挂起控制台(console_suspend_all());
  5. 按设备模型顺序挂起所有设备(dpm_suspend_start());
  6. 进入睡眠循环:suspend_enter(),若被假唤醒(!wakeup)且平台要求重试(platform_suspend_again())则重复;
  7. 恢复设备(dpm_resume_end())、恢复控制台,最后解冻进程并唤醒文件系统(suspend_finish())。

其中 S2Idle 走s2idle_ops回调链(prepare_latewakerestore_earlyrestore等,见 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/Kconfig:

  • CONFIG_SUSPEND:启用 Suspend to RAM 与 standby(依赖ARCH_SUSPEND_POSSIBLE,默认 y);
  • CONFIG_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 与 S3),S2RAM 凭借内存自刷新实现深度节能;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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 20:54:44

鸿蒙ArkUI组件Slider与Progress开发实战指南

1. 鸿蒙ArkUI组件Slider与Progress深度解析 作为鸿蒙应用开发的核心交互组件&#xff0c;Slider&#xff08;滑动条&#xff09;和Progress&#xff08;进度条&#xff09;在各类应用场景中扮演着重要角色。最近在开发一个健康管理应用时&#xff0c;我深刻体会到这两个组件的灵…

作者头像 李华
网站建设 2026/9/11 20:53:24

WorkBuddy实战:从聊天AI到AI Agent工作台的完整教程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华