news 2026/10/8 17:45:34

【Linux内核专栏 15】电源管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Linux内核专栏 15】电源管理

15 · 电源管理

本篇定位:嵌入式和移动设备,省电是硬指标。FreeRTOS 用 tickless idle + WFI;Linux 有完整电源管理框架:cpuidle(空闲状态)、cpufreq(频率调节)、Runtime PM(运行时按需开关设备)、系统级 suspend/hibernate、wakeup source(唤醒源)。本篇讲清这套,读完能给设备配省电策略、能调"为什么设备不休眠"。

Linux 电源管理是tickless/WFI 的系统化扩展
FreeRTOS 省电:tickless idle(进 WFI,停 tick)。Linux 省电复杂得多:①cpuidle(多级空闲状态,浅睡/深睡);②cpufreq(动态调频,按负载);③Runtime PM(设备不用就关);④suspend(整机睡眠);⑤wakeup source(什么能唤醒)。增量是"多级 + 设备级 + 系统级"。WFI 是 cpuidle 最浅一级。


目录

  • 15 · 电源管理
  • 一、电源管理的层次
  • 二、cpuidle:CPU 空闲状态
    • 2.1 为什么多级空闲
    • 2.2 idle state
    • 2.3 RISC-V idle
    • 2.4 看 cpuidle
    • 2.5 对照 FreeRTOS tickless
  • 三、cpufreq:动态调频(DVFS)
    • 3.1 DVFS 是什么
    • 3.2 cpufreq 框架
    • 3.3 governor(策略)
    • 3.4 看与配
    • 3.5 OPP(Operating Performance Points)
  • 四、Runtime PM:设备运行时电源管理⭐
    • 4.1 为什么 Runtime PM
    • 4.2 Runtime PM API
    • 4.3 runtime PM callback
    • 4.4 引用计数
    • 4.5 autosuspend(延迟挂起)
    • 4.6 看 Runtime PM
  • 五、系统级 Suspend(睡眠)
    • 5.1 suspend 状态
    • 5.2 suspend 流程
    • 5.3 沿设备树级联(10 篇)
    • 5.4 PM QoS(电源管理服务质量)
    • 5.5 触发 suspend
  • 六、wakeup source(唤醒源)
    • 6.1 什么是唤醒源
    • 6.2 注册唤醒源
    • 6.3 看唤醒源
    • 6.4 唤醒原因排查
  • 七、clock 和 regulator 框架
    • 7.1 clock framework
    • 7.2 regulator framework
    • 7.3 与 PM 关系
  • 八、PM ops 完整结构
  • 九、嵌入式省电策略
      • 9.1 常见策略
    • 9.2 嵌入式典型场景
    • 9.3 调试省电
  • 十、对照总表
  • 十一、本篇小结
  • 速查表

一、电源管理的层次

系统级: suspend(sleep) / hibernate(磁盘) / shutdown │ 子系统级: Runtime PM(设备按需开关) │ CPU 级: cpufreq(调频) + cpuidle(空闲状态) │ 硬件: DVFS(电压频率) / WFI / clock gating / power gating
层次作用触发
系统级整机睡眠/休眠用户(电源键)/超时
子系统级设备按需开关设备不忙时自动
CPU 级调频/空闲负载/空闲

二、cpuidle:CPU 空闲状态

2.1 为什么多级空闲

  • CPU 空闲可进不同睡眠深度
  • 浅睡(WFI):唤醒快,省电少
  • 深睡(power gating):唤醒慢,省电多
  • cpuidle 框架:按预计空闲时间选最优状态

2.2 idle state

structcpuidle_state{charname[CPUIDLE_NAME_LEN];unsignedintflags;int(*enter)(structcpuidle_device*dev,structcpuidle_driver*drv,intindex);intexit_latency;// 退出延迟(μs,唤醒要多久)inttarget_residency;// 目标驻留(μs,至少睡这么久才划算)intpower_usage;// 功耗(mW)...};
  • 每个 state 有退出延迟 + 目标驻留
  • idle 时间短选浅睡(快醒),长选深睡(省电)

2.3 RISC-V idle

  • 最浅:WFI(Wait For Interrupt),指令进低功耗
  • 更深:SoC 特定(关 PLL/关域)
  • cpuidle driver 注册多级

2.4 看 cpuidle

cat/sys/devices/system/cpu/cpu0/cpuidle/state*/name# WFI# RETENTION# POWER_OFFcat/sys/devices/system/cpu/cpu0/cpuidle/state*/disable# 0 (0=启用,1=禁用某状态)

2.5 对照 FreeRTOS tickless

FreeRTOS ticklessLinux cpuidle
空闲进WFI(常一级)多级 idle state
选哪级单级按预计空闲时间
唤醒中断中断
tick停停(NOHZ,08 篇)

tickless WFI 是 cpuidle 最浅级
FreeRTOS tickless 进 WFI——Linux cpuidle 的最浅 state(WFI)。Linux 多了深睡状态(关域/关 PLL),按空闲时长选。增量是多级 + 智能选择。WFI 经验直接迁移,新增"深睡的延迟/驻留权衡"。


三、cpufreq:动态调频(DVFS)

3.1 DVFS 是什么

  • Dynamic Voltage and Frequency Scaling
  • 负载低降频降压(省电),负载高升频升压(性能)
  • CPU + 调频驱动 + governor(策略)

3.2 cpufreq 框架

structcpufreq_driver{int(*init)(structcpufreq_policy*policy);int(*setpolicy)(...);// 设策略int(*target_index)(...);// 设频率...};structcpufreq_governor{int(*throttle)(...);unsignedint(*get)(...);...};
  • driver:硬件操作(SoC 调频接口)
  • governor:策略(什么时候调多少)

3.3 governor(策略)

governor策略用途
performance一直最高频性能优先
powersave一直最低频省电优先
userspace用户态指定手动
ondemand按负载升频通用(默认)
schedutil据调度器信息调现代(配合 EAS)
conservative渐进调频平衡

3.4 看与配

cat/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors# ondemand performance powersave ...cat/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq# 1200000 (1.2 GHz)cat/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies# 400000 800000 1200000 1600000# 改 governorechoperformance>/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor# 设固定频率echo800000>/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed

3.5 OPP(Operating Performance Points)

  • SoC 定义的"频率+电压"组合
  • DTS 描述:operating-points-v2
  • 调频驱动据 OPP 切换
cpu0_opp_table: opp-table { compatible = "oper-points-v2"; opp-400M { opp-hz = <400000000>; opp-microvolt = <900000>; }; opp-1G { opp-hz = <1000000000>; opp-microvolt = <1100000>; }; };

四、Runtime PM:设备运行时电源管理⭐

4.1 为什么 Runtime PM

  • 设备不忙时关它(省电),要用时开
  • 不等整机 suspend,运行时动态开关
  • 例:USB 设备空闲自动挂起

4.2 Runtime PM API

// 设备结构(继承 device,10 篇)structdevice{...structdev_pm_infopower;// PM 状态...};// 驱动用:pm_runtime_get_sync(dev);// 标记"要用",+1 计数,若 0→1 调 resumepm_runtime_put_sync(dev);// 标记"用完",-1,若 1→0 调 suspend// 或自动:pm_runtime_enable(dev);pm_runtime_set_autosuspend_delay(dev,2000);// 空闲 2s 后自动挂起pm_runtime_use_autosuspend(dev);pm_runtime_mark_last_busy(dev);

4.3 runtime PM callback

structdev_pm_ops{int(*runtime_suspend)(structdevice*dev);// 挂起int(*runtime_resume)(structdevice*dev);// 恢复int(*runtime_idle)(structdevice*dev);// 空闲(可决定挂起)...};// 驱动注册staticconststructdev_pm_opsmy_pm={SET_RUNTIME_PM_OPS(my_runtime_suspend,my_runtime_resume,NULL)};

4.4 引用计数

  • pm_runtime_get:计数 +1(要用)
  • pm_runtime_put:计数 -1(用完)
  • 计数 > 0:设备活跃
  • 计数 = 0:可挂起
  • 计数 0→1:调 resume;1→0:调 suspend

4.5 autosuspend(延迟挂起)

  • 不是用完立刻挂起(频繁开关损耗)
  • 空闲 N 秒后才挂起
  • pm_runtime_mark_last_busy+ autosuspend_delay

Runtime PM 是设备级省电,你裸机手动开关外设
裸机省电:不用 UART 时手动关时钟。Linux Runtime PM框架化:驱动实现 suspend/resume 回调,框架管引用计数,自动开关。写驱动加 dev_pm_ops,框架管时机。

4.6 看 Runtime PM

cat/sys/devices/.../power/control# on (on=禁止自动挂起,auto=允许)cat/sys/devices/.../power/runtime_status# active / suspended / suspending / resumingechoauto>/sys/devices/.../power/control# 允许自动echoon>/sys/devices/.../power/control# 禁止(常开)

五、系统级 Suspend(睡眠)

5.1 suspend 状态

状态名字特点
freeze冻结用户态最浅,只停进程
standby待机系统进低功耗,内存保持
mem挂起到内存(S3)内存自刷新,CPU/多数外设关
disk挂起到磁盘(休眠,S4)内存存盘后整机关

5.2 suspend 流程

echo mem > /sys/power/state → 内核 suspend 流程: 1. 冻结用户进程(信号停止) 2. 通知所有设备 suspend(dev_pm_ops.suspend) 3. 关中断 4. 关 CPU(进睡眠) ... 等唤醒 ... 唤醒: 5. 唤醒源触发 6. 恢复 CPU 7. 开中断 8. resume 设备(逆序) 9. 解冻进程

5.3 沿设备树级联(10 篇)

  • suspend 按设备树深度优先逆序:先子后父
  • resume 按设备树顺序:先父后子
  • 父设备(总线)先 resume,子设备才能用

5.4 PM QoS(电源管理服务质量)

  • 约束"不能睡太深"或"必须快醒"
  • 例:音频要低延迟,不能进深睡
  • pm_qos_add_request加约束

5.5 触发 suspend

echomem>/sys/power/state# 挂起到内存echodisk>/sys/power/state# 休眠echofreeze>/sys/power/state# 仅冻结# 看支持的状态cat/sys/power/state# freeze mem disk

六、wakeup source(唤醒源)

6.1 什么是唤醒源

  • 系统睡眠时,只有特定源能唤醒(中断)
  • wakeup source 标记"我能唤醒系统"
  • 例:电源键、网络(Wake-on-LAN)、RTC 闹钟、GPIO

6.2 注册唤醒源

// 设备启用唤醒能力device_set_wakeup_capable(dev,true);device_wakeup_enable(dev);// 中断唤醒(IRQF 之外)enable_irq_wake(irq);// 让该中断能唤醒disable_irq_wake(irq);

6.3 看唤醒源

cat/proc/acpi/wakeup# x86cat/sys/kernel/debug/wakeup_sources# 通用# 看哪些设备能唤醒fordin/sys/devices/*/*/power/wakeup;doecho"$d:$(cat$d)"done

6.4 唤醒原因排查

# 看上次唤醒原因cat/sys/kernel/debug/wakeup_sources# active_count / event_count / wakeup_count / expire_count# last_time / max_time / total_time

嵌入式唤醒调试是难点
嵌入式产品:“睡眠了但被意外唤醒"或"睡眠后唤醒不来”。排查:①/sys/kernel/debug/wakeup_sources看哪个源触发;② 检查设备 wakeup_enabled;③ enable_irq_wake 是否对。这是嵌入式 BSP 省电调试的核心。


七、clock 和 regulator 框架

7.1 clock framework

  • SoC 时钟树复杂(PLL/分频/gating)
  • clock framework 统一管理
  • 驱动clk_get/clk_prepare_enable/clk_disable_unprepare
structclk*clk=clk_get(dev,NULL);clk_prepare_enable(clk);// 开时钟// 用设备clk_disable_unprepare(clk);

7.2 regulator framework

  • 电源调节器(LDO/DCDC)
  • 驱动regulator_get/regulator_enable/regulator_set_voltage
structregulator*r=devm_regulator_get(dev,"vdd");regulator_enable(r);regulator_set_voltage(r,1100000,1100000);

7.3 与 PM 关系

  • cpufreq 调频要同步调压(调 regulator)
  • suspend 关时钟(clock gating)
  • DVFS = clock(频率)+ regulator(电压)联动

八、PM ops 完整结构

structdev_pm_ops{/* 系统 suspend/resume */int(*suspend)(...);int(*resume)(...);int(*freeze)(...);int(*thaw)(...);int(*poweroff)(...);int(*restore)(...);/* Runtime PM */int(*runtime_suspend)(...);int(*runtime_resume)(...);int(*runtime_idle)(...);/* ... 完整版更多 */};// 驱动用宏简化staticconststructdev_pm_opsmy_pm={SET_SYSTEM_SLEEP_PM_OPS(my_suspend,my_resume)// 系统 suspendSET_RUNTIME_PM_OPS(my_rt_suspend,my_rt_resume,NULL)// Runtime PM};
  • 系统 suspend 和 Runtime PM 是两套
  • 驱动可只实现一套或都实现

九、嵌入式省电策略

9.1 常见策略

策略工具
CPU 调频cpufreq ondemand/schedutil
CPU 空闲cpuidle 多级
设备按需开关Runtime PM
整机睡眠suspend mem(无任务时)
关外设时钟clock gating
关未用域power gating(SoC 级)
唤醒源只留必要(电源键/RTC/网络)

9.2 嵌入式典型场景

  • 电池产品(手持):cpufreq ondemand + cpuidle 深睡 + Runtime PM + 空闲 suspend
  • 常电产品( plugged):cpufreq performance + 禁深睡(低延迟优先)
  • 边缘 AI:高性能时全频,空闲降频

9.3 调试省电

# 看功耗(若有功率计)# 看 CPU 频率/状态cat/sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freqcat/sys/devices/system/cpu/cpu*/cpuidle/state*/usage# 看设备 PM 状态cat/sys/devices/.../power/runtime_status# 看唤醒源cat/sys/kernel/debug/wakeup_sources# powertop(省电分析工具)powertop

嵌入式视角:powertop 是省电调优利器
Ubuntu 有 powertop,扫系统给出"哪些设备可省电"“哪些 wakeup 频繁”。嵌入式虽不一定有 powertop,但思路通用:① 找异常活跃设备;② 禁不必要唤醒;③ 配 Runtime PM。你 AEGIX 省电产品可参考。


十、对照总表

概念FreeRTOS/裸机Linux PM
CPU 空闲WFIcpuidle 多级
调频手动cpufreq + governor
设备开关手动Runtime PM
整机睡眠无(或自己写)suspend(mem/disk)
唤醒源中断wakeup source
时钟管理手动配clock framework
电压管理手动regulator framework
省电策略tickless多层组合
调试电流计powertop/wakeup_sources

十一、本篇小结

  • cpuidle:CPU 空闲多级状态(WFI 浅/深睡),按预计空闲时间选,exit_latency/target_residency 权衡
  • cpufreq:DVFS 动态调频,governor(performance/ondemand/schedutil),DTS OPP 描述频率电压
  • Runtime PM:设备运行时按需开关,引用计数(pm_runtime_get/put),autosuspend 延迟挂起,dev_pm_ops runtime_suspend/resume
  • 系统 suspend:freeze/standby/mem/disk,沿设备树级联(子先 suspend,父先 resume)
  • wakeup source:标记能唤醒系统的源,enable_irq_wake,排查/sys/kernel/debug/wakeup_sources
  • clock framework:统一时钟管理(clk_prepare_enable);regulator framework:电源调压
  • PM ops:系统 suspend 和 Runtime PM 两套,SET_SYSTEM_SLEEP_PM_OPS / SET_RUNTIME_PM_OPS
  • 嵌入式省电:cpufreq ondemand + cpuidle 深睡 + Runtime PM + 空闲 suspend + 只留必要唤醒源
  • FreeRTOS tickless WFI = cpuidle 最浅级,增量是多级 + 设备级 + 系统级

速查表

想干啥用什么
看 CPU 频率cat /sys/…/cpu/cpu0/cpufreq/scaling_cur_freq
改 governorecho ondemand > /sys/…/scaling_governor
设固定频率echo Hz > /sys/…/scaling_setspeed
看 idle 状态cat /sys/…/cpu0/cpuidle/state*/name
禁某 idle 状态echo 1 > /sys/…/cpu0/cpuidle/state3/disable
看设备 PM 状态cat /sys/devices/…/power/runtime_status
禁设备自动挂起echo on > /sys/devices/…/power/control
系统挂起echo mem > /sys/power/state
看支持睡眠状态cat /sys/power/state
看唤醒源cat /sys/kernel/debug/wakeup_sources
让中断唤醒enable_irq_wake(irq)
开时钟clk_prepare_enable(clk)
设电压regulator_set_voltage
省电分析powertop
Runtime PM 引用pm_runtime_get_sync / pm_runtime_put_sync

💡技术之路漫漫,分享是为了更好地交流。如果本文的内容对你有启发,希望能得到你的点赞 👍和收藏 ⭐。

如果你在调试过程中遇到了其他问题,欢迎在评论区 💬留言,我们一起探讨。也欢迎关注 👀我,一起交流底层开发的那些事儿。


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

SOM神经网络:无监督聚类与可视化解释实战指南

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

作者头像 李华