kernel/power 内核电源管理与休眠机制与原理详解
源码路径:rk3588/kernel-6.1/kernel/power/
内核版本:Linux 6.1(RK3588 平台)
平台:RK3588(4×Cortex-A76 + 4×Cortex-A55 big.LITTLE,ARM64)
该目录实现 Linux 系统级睡眠(System Sleep) 与 电源管理基础设施:Suspend-to-RAM(STR)、Suspend-to-Idle(S2Idle)、Hibernation(STD/swsusp)、进程冻结、PM QoS、Energy Model,以及 /sys/power 用户接口。设备运行时 PM(runtime suspend)的核心逻辑在 drivers/base/power/,但系统休眠路径通过 DPM(Device Power Management) 与本目录紧密协作。
定位:协调「整机睡眠/唤醒」的框架层;平台相关休眠入口由 arch/arm64/ 与 drivers/soc/rockchip/ 通过 suspend_set_ops() 注册。
目录
一、源码目录结构
1.1 编译依赖(Makefile)
1 2 3 4 5 6 7 8 9 10 11 12 13
| obj-y += qos.o
obj-$(CONFIG_PM) += main.o obj-$(CONFIG_FREEZER) += process.o obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o obj-$(CONFIG_HIBERNATION_SNAPSHOT_DEV) += user.o obj-$(CONFIG_PM_AUTOSLEEP) += autosleep.o obj-$(CONFIG_PM_WAKELOCKS) += wakelock.o obj-$(CONFIG_ENERGY_MODEL) += energy_model.o obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
|
| 配置项 |
说明 |
CONFIG_PM |
设备 PM 核心(本目录 main.c 部分功能) |
CONFIG_PM_SLEEP |
系统睡眠(依赖 SUSPEND 或 HIBERNATE_CALLBACKS) |
CONFIG_SUSPEND |
Suspend-to-RAM / Standby / S2Idle |
CONFIG_HIBERNATION |
休眠到磁盘(swsusp) |
CONFIG_FREEZER |
睡眠前冻结用户态/内核线程 |
CONFIG_PM_AUTOSLEEP |
无 wakeup source 时自动睡眠 |
CONFIG_PM_WAKELOCKS |
用户态 wakelock 接口 |
CONFIG_ENERGY_MODEL |
DVFS 设备能耗模型(调度/thermal 用) |
CONFIG_SUSPEND_FREEZER |
STR 前冻结进程(默认 y) |
Kconfig 位于 kernel/power/Kconfig(由 arch/arm64/Kconfig source)。
1.2 源文件
| 文件 |
行数 |
功能 |
snapshot.c |
2756 |
内存快照:PBE、页面备份/恢复、镜像读写 |
hibernate.c |
1367 |
休眠流程编排、平台回调、resume 参数 |
swap.c |
1619 |
快照镜像读写 swap 分区 |
main.c |
940 |
PM 核心:sysfs、notifier、state 入口、统计 |
qos.c |
678 |
PM QoS 约束聚合(latency、flags) |
suspend.c |
648 |
STR/S2Idle 状态机、platform ops |
energy_model.c |
438 |
CPU/GPU 等平台能耗表注册 |
user.c |
466 |
uswsusp 用户态快照设备 |
wakelock.c |
285 |
用户态 wakelock(Android 兼容) |
process.c |
235 |
睡眠前 freeze/thaw 进程 |
suspend_test.c |
219 |
启动时 test_suspend 自检 |
console.c |
152 |
VT 控制台 suspend/resume |
autosleep.c |
129 |
opportunistic sleep |
poweroff.c |
45 |
SysRq 关机辅助 |
power.h |
328 |
内部 API、swsusp 结构 |
相关目录(目录外):
| 路径 |
功能 |
drivers/base/power/ |
设备 runtime PM、wakeup source、DPM |
kernel/freezer.c |
任务 refrigerator 机制 |
arch/arm64/kernel/suspend.c |
CPU 级 suspend/resume(cpu_suspend) |
drivers/soc/rockchip/ |
RK 平台 suspend 模式、lite/ultra |
二、整体架构
2.1 子系统分层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 用户空间 echo mem > /sys/power/state /sys/power/autosleep, wakeup_count, mem_sleep │ ▼ kernel/power/ ← 本目录(系统睡眠框架) main.c — sysfs、pm_notifier、pm_suspend 入口 suspend.c — STR/S2Idle 流程 hibernate.c + snapshot.c + swap.c — STD process.c — freezer qos.c / energy_model.c — 约束与能耗 │ ├── dpm_suspend_* / dpm_resume_* → drivers/base/power/ ├── syscore_suspend / syscore_resume └── suspend_ops->enter() → 平台(Rockchip ATF/PSCI) │ ▼ arch/arm64/kernel/suspend.c — cpu_suspend / __cpu_suspend_enter drivers/soc/rockchip/ — ROCKCHIP_SUSPEND_MODE 等
|
2.2 与 Runtime PM 的区别
| 维度 |
System Sleep(本目录) |
Runtime PM(drivers/base/power) |
| 粒度 |
整机 |
单个 device |
| 触发 |
/sys/power/state、autosleep |
pm_runtime_suspend() |
| 进程 |
通常 freeze 全部用户进程 |
不 freeze |
| 状态 |
PM_SUSPEND_MEM 等 |
runtime_status |
两者通过 DPM 在系统休眠时统一 suspend 所有设备。
三、睡眠状态与术语
3.1 suspend_state_t
| 枚举 |
pm_labels(state) |
mem_sleep_labels |
含义 |
PM_SUSPEND_TO_IDLE |
freeze |
s2idle |
冻结进程+设备,CPU 进 idle |
PM_SUSPEND_STANDBY |
standby |
shallow |
浅睡(平台相关) |
PM_SUSPEND_MEM |
mem |
deep |
深睡 STR(内存保持) |
PM_SUSPEND_MAX |
— |
— |
写入 “disk” 触发 hibernate |
RK 平台扩展(CONFIG_ROCKCHIP_LITE_ULTRA_SUSPEND):
| 状态 |
mem_sleep |
说明 |
PM_SUSPEND_MEM_LITE |
lite |
电子书等场景的轻量 mem 睡眠 |
PM_SUSPEND_MEM_ULTRA |
ultra |
更深度的 ultra 睡眠 |
写入 mem_sleep 时选择实际 mem_sleep_current;pm_suspend() 会将 lite/ultra 映射为 PM_SUSPEND_MEM 再进入平台代码。
3.2 全局变量
1 2 3
| suspend_state_t mem_sleep_current; suspend_state_t pm_suspend_target_state; struct mutex system_transition_mutex;
|
四、核心入口与 Sysfs(main.c)
4.1 /sys/power/ 主要属性
| 属性 |
读写 |
功能 |
state |
RW |
写入 mem/freeze/disk 触发睡眠 |
mem_sleep |
RW |
选择 s2idle/shallow/deep(及 lite/ultra) |
sync_on_suspend |
RW |
睡眠前是否 sync() 文件系统 |
wakeup_count |
RW |
与 wakeup event 配合避免竞态 |
pm_async |
RW |
设备异步 suspend/resume |
pm_test |
RW |
调试:在指定阶段停止(freezer/devices/platform…) |
pm_print_times |
RW |
打印各设备 suspend/resume 耗时 |
autosleep |
RW |
opportunistic sleep 目标状态 |
wake_lock / wake_unlock |
WO |
用户态 wakelock(CONFIG_PM_WAKELOCKS) |
4.2 state_store 流程
1 2 3 4
| state = decode_state(buf, n); if (state == PM_SUSPEND_MEM) state = mem_sleep_current; error = pm_suspend(state);
|
4.3 PM Notifier
1 2
| static BLOCKING_NOTIFIER_HEAD(pm_chain_head); register_pm_notifier() / pm_notifier_call_chain()
|
通知阶段包括 PM_SUSPEND_PREPARE、PM_POST_SUSPEND、PM_HIBERNATION_PREPARE 等,供子系统(如 CPUFreq)在睡眠前后调整状态。
4.4 lock_system_sleep()
1 2
| current->flags |= PF_NOFREEZE; mutex_lock(&system_transition_mutex);
|
防止睡眠线程自身被 freezer 冻结;与 hibernation 的 snapshot 读写路径配合。
五、Suspend-to-RAM(suspend.c)
5.1 平台操作表
1 2 3
| static const struct platform_suspend_ops *suspend_ops;
void suspend_set_ops(const struct platform_suspend_ops *ops);
|
典型回调:
| 回调 |
时机 |
valid(state) |
检查平台是否支持该睡眠状态 |
prepare() |
设备 suspend 之前 |
prepare_late() |
dpm_suspend_late 前后 |
enter(state) |
关中断、停从核、进硬件睡眠 |
wake() |
唤醒后早期处理 |
S2Idle 另有 platform_s2idle_ops(prepare/check/wake)。
5.2 enter_state() — 顶层流程
1 2 3 4 5 6 7 8 9 10 11 12
| mutex_trylock(system_transition_mutex) sync_on_suspend → ksys_sync_helper()(可选) suspend_prepare(state) ├── pm_notifier PM_SUSPEND_PREPARE ├── suspend_freeze_processes() ← process.c ├── dpm_suspend_start(PMSG_SUSPEND) └── platform prepare suspend_devices_and_enter(state) suspend_finish() ├── thaw_processes() └── pm_notifier PM_POST_SUSPEND mutex_unlock(system_transition_mutex)
|
5.3 suspend_devices_and_enter()
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| suspend_console() dpm_suspend_start(PMSG_SUSPEND) /* 设备 early suspend */ suspend_enter(state) ├── dpm_suspend_late() ├── dpm_suspend_noirq() ├── [S2Idle] s2idle_loop() ├── [STR] pm_sleep_disable_secondary_cpus() │ syscore_suspend() │ suspend_ops->enter(state) ← 平台进睡眠 │ syscore_resume() │ pm_sleep_enable_secondary_cpus() └── dpm_resume_noirq / early / finish dpm_resume_end(PMSG_RESUME) resume_console()
|
5.4 Suspend-to-Idle(S2Idle)
不调用 suspend_ops->enter(),而是:
1 2 3
| s2idle_loop(): wake_up_all_idle_cpus() /* 所有 CPU 进 idle */ swait_event(s2idle_wait_head) /* 等待 wakeup */
|
等价于:冻结进程 + 设备 suspend + CPU idle,功耗低于运行态但通常高于 STR。
5.5 suspend 统计
1
| struct suspend_stats suspend_stats;
|
可通过 debugfs suspend_stats 或 sysfs suspend_stats/ 查看。
六、进程冻结(process.c)
睡眠前须冻结用户态与可冻结内核线程,防止持有锁或 DMA 的进程在设备已 suspend 后继续运行。
6.1 freeze_processes()
1 2 3 4 5
| __usermodehelper_disable(UMH_FREEZING) current->flags |= PF_SUSPEND_TASK pm_freezing = true try_to_freeze_tasks(user_only=true) /* 对每个 task freeze_task() */ oom_killer_disable()
|
6.2 freeze_kernel_threads()
1 2
| pm_nosig_freezing = true try_to_freeze_tasks(user_only=false) /* 含 workqueue */
|
6.3 thaw_processes()
1 2 3 4
| oom_killer_enable() thaw_workqueues() __thaw_task() 对所有进程 usermodehelper_enable()
|
超时默认 freeze_timeout_msecs = 20s;失败时打印 refusing-to-freeze 任务栈。
七、Hibernation 休眠到磁盘(hibernate.c / snapshot.c / swap.c)
7.1 原理(swsusp)
- 冻结进程、quiesce 设备
- snapshot.c:将内存页写入 PBE(Page Backup Entry) 链表,生成连续镜像
- swap.c:镜像压缩(LZO 等)写入 swap 分区
- 关机或重启
- 下次启动带
resume=/dev/swap:从 swap 读镜像、snapshot 恢复内存、跳回原内核上下文
7.2 关键结构(power.h)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| struct swsusp_info { struct new_utsname uts; u32 version_code; unsigned long num_physpages; int cpus; unsigned long image_pages; ... };
struct snapshot_handle { unsigned int cur; void *buffer; int sync_read; };
|
镜像通过 snapshot_read_next() / snapshot_write_next() 以 PAGE_SIZE 块流式读写。
7.3 hibernation_snapshot() 概要
1 2 3 4 5 6
| platform_begin() dpm_suspend_start(PMSG_FREEZE) create_basic_memory_bitmaps() swsusp_alloc() / swsusp_save() ← snapshot.c,保存 CPU/内存状态 swsusp_write(flags) ← swap.c,写 swap platform_finish()
|
7.4 恢复路径
1 2 3 4
| swsusp_check() — 检测 swap 上有效镜像 swsusp_read() — 读入镜像 restore_highmem() / resume_target_kernel() arch 相关:swsusp_arch_resume、enable_restore_image_protection
|
7.5 平台模式
1 2
| enum { HIBERNATION_PLATFORM, HIBERNATION_SHUTDOWN, HIBERNATION_REBOOT, ... }; hibernation_set_ops(platform_hibernation_ops);
|
ARM64 支持 ARCH_HIBERNATION_POSSIBLE + ARCH_HIBERNATION_HEADER。
八、PM QoS(qos.c)
Quality of Service 约束框架:多个请求者注册 latency/flags 需求,内核聚合为 target_value。
1 2 3
| int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, enum pm_qos_req_action action, int value);
|
| 聚合类型 |
规则 |
PM_QOS_MIN |
取 plist 最小值(最严格 latency 要求) |
PM_QOS_MAX |
取最大值 |
变更时通过 blocking_notifier_call_chain(c->notifiers) 通知 CPUIdle/CPUFreq 等子系统。
常见约束:CPU latency QoS、freq QoS、device PM QoS flags(dev_pm_qos_* 在 drivers/base/power)。
九、Energy Model(energy_model.c)
为 DVFS 设备(主要是 CPU)注册 性能状态 → 功耗/成本 表,供调度器(EAS)、thermal 使用。
1 2 3 4 5
| struct em_perf_domain { struct em_perf_state *table; unsigned int nr_perf_states; struct cpumask *cpus; };
|
驱动通过 em_dev_register_perf_domain() 注册;debugfs 位于 /sys/kernel/debug/energy_model/。
RK3588 big.LITTLE 场景下,A76/A55 各 cluster 可注册独立 perf domain,调度器据此做能效感知选核。
十、Autosleep 与 Wakelock
10.1 autosleep.c
1 2 3 4 5
| try_to_suspend(work): pm_save_wakeup_count() pm_suspend(autosleep_state) 或 hibernate() queue_up_suspend_work()
|
仅当 无 active wakeup source 时进入睡眠;与 Android 式 power manager 类似。
10.2 wakelock.c
用户态通过 /sys/power/wake_lock、wake_unlock 创建 wakeup_source:
1 2 3 4
| struct wakelock { struct rb_node node; struct wakeup_source *ws; };
|
__pm_stay_awake() / __pm_relax() 阻止 autosleep;可选 GC(PM_WAKELOCKS_GC)回收长期未用 wakelock。
十一、辅助组件
| 文件 |
功能 |
console.c |
VT 控制台在睡眠前后 save/restore |
user.c |
/dev/snapshot 字符设备,uswsusp 用户态休眠 |
suspend_test.c |
内核参数 test_suspend=mem 启动时自动测 suspend |
poweroff.c |
Magic SysRq 触发 orderly poweroff |
tracking.c |
记录已卸载 taint 模块(debugfs) |
十二、RK3588/ARM64 平台说明
12.1 ARM64 架构支持
| 配置 |
值 |
说明 |
ARCH_SUSPEND_POSSIBLE |
y |
支持 STR |
ARCH_HIBERNATION_POSSIBLE |
y |
依赖 CPU_PM |
ARCH_HIBERNATION_HEADER |
y |
休眠镜像含 arch 头 |
CPU_PM |
select if SUSPEND |
CPU 电源管理 |
arch/arm64/kernel/suspend.c 提供 cpu_suspend():
1 2 3 4 5 6 7 8
| int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) { if (__cpu_suspend_enter(&state)) ret = fn(arg); else __cpu_suspend_exit(); }
|
12.2 Rockchip 平台扩展
| 配置 |
说明 |
ROCKCHIP_SUSPEND_MODE |
通过 ATF 配置 suspend 模式 |
ROCKCHIP_LITE_ULTRA_SUSPEND |
mem_sleep 增加 lite/ultra(电子书等) |
ROCKCHIP_SUSPEND_DEBUG |
suspend 调试 |
ROCKCHIP_SYSTEM_MONITOR |
系统 monitor、early suspend |
平台驱动在 init 时调用 suspend_set_ops(&rockchip_suspend_ops),.enter() 最终通过 PSCI SYSTEM_SUSPEND 或 Rockchip ATF 进入硬件低功耗。
12.3 RK3588 常用操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| cat /sys/power/state
cat /sys/power/mem_sleep
echo mem > /sys/power/state
echo freeze > /sys/power/state
read /sys/power/wakeup_count echo mem > /sys/power/state
|
12.4 big.LITTLE 注意点
- STR 时 非 boot CPU 离线,boot CPU 在
suspend_ops->enter() 中最后进入 WFI/平台睡眠
- 唤醒后 secondary CPU 重新 online;cpuidle 在
pm_sleep_disable/enable_secondary_cpus() 中 pause/resume
- Energy Model 与 EAS 调度器配合,影响 睡眠前选核 与 唤醒后负载迁移(逻辑在
kernel/sched/ 与 drivers/cpufreq/)
十三、完整 Suspend 时序
十四、总结
| 组件 |
职责 |
| main.c |
/sys/power 接口、PM notifier、睡眠入口协调 |
| suspend.c |
STR/S2Idle 状态机、DPM 与 platform ops 编排 |
| process.c |
睡眠前 freezer |
| hibernate.c + snapshot.c + swap.c |
休眠到磁盘完整实现 |
| qos.c |
PM QoS 约束聚合 |
| energy_model.c |
DVFS 能耗表(EAS/thermal) |
| autosleep.c / wakelock.c |
opportunistic sleep 与 Android 式唤醒锁 |
kernel/power/ 是 Linux 系统级电源管理 的中枢;RK3588 实际进深睡依赖 Rockchip 平台驱动与 ATF/PSCI,本目录提供标准流程与 sysfs 接口。设备级 runtime PM 请结合 drivers/base/power/ 与具体驱动 dev_pm_ops 一并理解。
附录:源文件清单
| 文件 |
行数 |
kernel/power/snapshot.c |
2756 |
kernel/power/hibernate.c |
1367 |
kernel/power/swap.c |
1619 |
kernel/power/main.c |
940 |
kernel/power/qos.c |
678 |
kernel/power/suspend.c |
648 |
kernel/power/energy_model.c |
438 |
kernel/power/user.c |
466 |
kernel/power/wakelock.c |
285 |
kernel/power/process.c |
235 |
kernel/power/suspend_test.c |
219 |
kernel/power/console.c |
152 |
kernel/power/autosleep.c |
129 |
kernel/power/poweroff.c |
45 |
kernel/power/power.h |
328 |
kernel/power/Kconfig |
354 |
kernel/power/Makefile |
24 |
| 合计 |
~10305 |
关联源码(目录外):
| 文件 |
说明 |
drivers/base/power/main.c |
设备 PM 核心 |
kernel/freezer.c |
任务 refrigerator |
arch/arm64/kernel/suspend.c |
CPU suspend 汇编入口 |
drivers/soc/rockchip/ |
RK3588 平台 suspend 配置 |
正在加载留言…