2. Linux Kernel Static Power Management

2023-05-16

Static Power Management 用于设备处于 Inactive 状态时,消耗尽可能少的功率。即长时间不使用设备时,比如:手机息屏后待机场景。这种策略基于整个系统的全局低功耗状态,在这种状态下用户空间代码无法执行并且整个系统活动显著减少,称为睡眠状态

当用户空间请求时,内核将系统置于这些状态之一,并且系统停留在其中,直到从指定设备之一接收到特殊信号(比如 Alarm 或 Modem 硬件中断),触发转换到用户空间代码可以运行的工作状态。因为睡眠状态是全局的,并且整个系统都会受到状态变化的影响,所以这种策略也被称为 system-wide power management (系统范围的电源管理)。

系统睡眠状态

根据其配置和运行平台的功能,Linux 内核可以支持多达四种系统睡眠状态,包括 hibernation (冬眠)和多达三种 system suspend(系统暂停)变体。下面列出了内核可以支持的睡眠状态:

  • Suspend-to-Idle ('freeze')

  • Power-on suspend ('standby')

  • Suspend-to-RAM ('mem')

  • Suspend-to-Disk ('disk')

在这几种状态中,设备睡眠程度越来越深,更加节省能源,也意味着睡眠和恢复的过程需要更长的时间以及消耗更多能源。

Android 设备仅支持 freeze 和 mem 两种状态。

Suspend-to-Idle('freeze')

这是一个通用的、纯软件的、轻量级的系统暂停(system suspend)(也被称为 S2I 或 S2Idle)的变体。

它通过下面的操作使处理器在系统暂停时可以在其最深的空闲状态下停滞更多的时间,从而相对于运行时空闲节省更多能源:

  1. 冻结用户空间

  2. 暂停计时

  3. 将所有I/O设备置于低功耗状态(可能比工作状态下的功耗更低)

该状态下系统可被带内中断唤醒(in-band interrupts),所以理论上任何能在工作状态下导致中断产生的设备也可以被设置为 S2Idle 的唤醒设备。

此状态可以在不支持 standby 或 Suspend-to-RAM 的平台上使用,也可以与任何更深层次的系统暂停变体一起使用,以减少恢复延迟(resume latency)。如果设置了 CONFIG_SUSPEND 内核配置选项,则始终支持它。

Power-on suspend ('standby')

这种状态,如果得到支持,可以提供适度但真实的能源节约,同时提供一个相对直接的过渡到工作状态。没有工作状态丢失(系统核心逻辑保留了电源),所以系统可以很容易地回到它离开的地方。它执行的操作包括:

  1. 冻结用户空间

  2. 暂停计时

  3. 将所有的I/O设备置于低功耗状态

  4. 非启动的CPU也会离线

  5. 所有的低级系统功能在过渡到这个状态时也会暂停

相对于 suspend-to-idle,它应该可以节省更多的能量,但是恢复的延迟通常会大。

Suspend-to-RAM ('mem')

这种状态(也被称为 STR 或 S2RAM)可以大大节省能源。因为系统中除了 memory(DDR)的所有东西,包括CPU,都进入了低功耗状态,通常都会断电。memory 进入自我刷新模式以保留其内容。

在进入 standby 状态时进行的所有步骤在过渡到 S2RAM 时也会进行。额外的操作可能会发生,这取决于平台的能力。特别是,在基于ACPI的系统中,内核在 S2RAM 转换过程中的最后一步将控制权交给平台固件(BIOS),这通常会导致关闭一些不受内核直接控制的低级组件。

Devices 和 CPU 的状态被保存并保留在内存中。所有设备都被暂停并进入低功耗状态。在许多情况下,所有外围总线在进入 S2RAM 时都会失去电源,因此设备必须能够处理返回 "on" 状态的过渡。

在基于 ACPI 的系统中,S2RAM 需要平台固件中的一些最小的启动限制代码,以便从它恢复系统。在其他平台上也可能是这样的情况。

相对于 suspend-to-idlestandby,能够从 S2RAM 唤醒系统的设备集通常会减少,可能有必要依靠平台来酌情设置唤醒功能。

如果设置了 CONFIG_SUSPEND 内核配置选项,并且平台在核心系统暂停子系统中注册了对它的支持,那么S2RAM就会得到支持。在基于 ACPI 的系统上,它被映射到 ACPI 定义的S3系统状态。

Android 使用 S2RAM 作为息屏待机时使用的休眠状态。

Suspend-to-Disk ('disk')

这种状态(也被称为 Hibernation(冬眠) 或 Suspend-to-Disk 或 STD)提供了最大的能源节约,即使在没有低级平台支持系统暂停的情况下也可以使用。然而,它需要一些用于恢复系统的底层 CPU 架构的低级代码。

Hibernation 相比于 S2RAM 明显的优势是 memory (DDR)也将断电,它与任何系统暂停的变体都有明显不同。它进入休眠状态需要三个系统状态变化,恢复则需要两个系统状态变化:

  • 系统休眠时 :

  1. 首先,当休眠被触发时,内核会停止所有的系统活动,并创建一个内存的快照 image;

  2. 接下来,系统进入一个可以保存快照 image 的状态,image 被写入到持久性存储(EMMC or UFS)中;

  3. 最后系统进入目标低功耗状态,在这个状态下,除了有限的一组唤醒设备外,几乎所有的硬件组件,包括内存,都被切断电源。

一旦快照图像被写出来,系统可以进入一个特殊的低功耗状态(如ACPI S4),或者干脆自己断电。关机意味着最小的耗电,它使这种机制在任何系统上都能发挥作用。然而,进入特殊的低功耗状态可能允许使用额外的系统唤醒手段(例如按键盘上的一个键或打开笔记本电脑的盖子)。

  • 系统恢复时:

  1. 唤醒后,控制权转到平台固件,该固件运行一个启动加载器,启动一个新的内核实例(控制权也可能直接转到启动加载器,这取决于系统配置,但无论如何,它都会导致一个新的内核实例被启动)。内核的新实例(被称为 restore kernel)在持久性存储中寻找 hibernation image ,如果找到了,就把它装入内存。

  2. 接下来,系统中的所有活动都被停止,还原内核用图像内容覆盖自己,并跳转到存储在 image 中的原始内核中的一个特殊蹦床区域(被称为 image kernel),这就是需要特殊架构的低级代码的地方。最后,图像内核将系统恢复到休眠前的状态,并允许用户空间再次运行。

如果设置了 CONFIG_HIBERNATION 内核配置选项,就支持 Hibernation 。然而,只有当对给定的CPU架构的支持包括系统恢复的低级代码时,才能设置这个选项。

系统暂停(System Suspend)和冬眠(Hibernation)的基本sysfs接口

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

state

这个文件包含一个字符串的列表,代表内核支持的睡眠状态。把这些字符串中的一个写进去,会使内核开始将系统转换到该字符串所代表的睡眠状态。

$cat /sys/power/state freeze standby mem disk

android 仅支持 freeze 和 mem。通常:

  • "freeze" 对应 Suspend-to-Idle

  • "standby" 对应 Standby(Power-on suspend)

  • "disk" 对应 Hibernation (Suspend-to-Disk )

而 "mem" 有多个变体,具体由文件 mem_sleep 的内容解释

mem_sleep

该文件包含一个代表支持的系统暂停变体的字符串列表,并允许用户空间选择与上述状态文件中的 "mem "字符串相关的变体。

$cat /sys/power/mem_sleep s2idle shallow [deep]
  • "s2idle" 代表 Suspend-to-idle

  • "shallow" 代表 Standby(Power-on suspend)

  • "deep" 代表 Suspend-to-RAM

在这个文件中写入一个列出的字符串会导致它所代表的系统暂停的变体与state文件中的 "mem "字符串相关联。代表当前与state文件中的 "mem "字符串相关联的暂停变量的字符串在方括号中显示。

根据上述可知,有两种方法可以使系统进入 Suspend-to-idle 状态:

  1. 直接向 /sys/power/state 写入 "freeze"

  2. 把 "s2idle" 写到 /sys/power/mem_sleep,然后把 "mem" 写到 /sys/power/state

同样,如果平台支持待机状态,也有两种方法可以使系统进入 Standby(Power-on suspend) 状态:

  1. 直接向 /sys/power/state 写入 "standby "

  2. 把 "shallow" 写到 /sys/power/mem_sleep,然后把 "mem" 写到 /sys/power/state

然而,只有一种方法可以使系统进入 Suspend-to-RAM 状态:

  1. "deep" 写入 /sys/power/mem_sleep,"mem" 写入 /sys/power/state

disk

这个文件控制 hibernation(Suspend-to-Disk)的操作模式。具体来说,它告诉内核在创建 hibernation image 后要做什么。

$cat /sys/power/disk 
platform [shutdown] reboot suspend test_resume
  • platform

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

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

  • shutdown

关闭系统电源。

  • reboot

重新启动系统(主要对诊断有用)。

  • suspend

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

如果支持系统挂起,它就可用。可作为 S2RAM 状态增强稳定性的缓解措施,用于解决 DDR 不稳定,其他子系统 panic 或者断电等异常使得机器无法从 S2RAM 正常恢复到休眠前的状态。

  • test_resume

诊断操作。加载镜像,就像系统刚刚从 hibernation 中醒来,当前运行的内核实例是一个 restore kernel,然后跟进全系统恢复。

将上面列出的一个字符串写进这个文件,会使它所代表的选项被选中。

当前选择的选项显示在方括号中,这意味着当 hibernation 被触发时,通过向/sys/power/state写入 "disk",它所代表的操作将在创建和保存镜像之后进行。

image_size

这个文件控制 hibernation images 的大小。

从中读取返回当前的 image 大小限制,默认情况下,它被设置为可用RAM大小的2/5左右。

pm_trace

这个文件控制着 "PM跟踪" 机制,在RTC内存中保存最后一个暂停或恢复的事件点,跨越重启。它有助于更有效地调试在系统挂起或恢复过程中发生的设备驱动程序故障导致的硬锁定或重启(这种情况更常见)。

如果它包含 "1",每个暂停/恢复事件点的指纹将依次存储在RTC存储器中(覆盖实际的RTC信息),因此,如果系统崩溃在存储后立即发生,它将幸存下来,并且可以在以后用来识别导致崩溃发生的驱动程序。

它默认包含 "0",可以通过写一个代表非零整数的字符串来改变为 "1"。

参考

[1]. System Sleep States

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

2. Linux Kernel Static Power Management 的相关文章

  • 如何真正释放 Linux 中的大页面以供新进程使用?

    真的找不到太多关于此的信息 希望有人可以提供帮助 我正在假脱机使用 100GB java 堆作为大数据缓存 为了避免与文件系统缓存等内容发生冲突 并且因为它通常性能更好 我将其分配在大页面中 我保留了 51 200 x 2MB 大页面 一切
  • C++ 模板静态成员实例化

    include
  • 在键盘热插拔上加载模块

    我正在尝试学习如何为 Linux 系统编写模块和驱动程序 类似于this https unix stackexchange com questions 120839 usb kernel module does not load on de
  • Bash 中 $() 和 () 之间的区别

    当我打字时ls l echo file 支架的输出 这只是简单的回显 被获取并传递到外部ls l命令 就等于简单的ls l file 当我打字时ls l echo file 我们有错误 因为不能嵌套 内部外部命令 有人可以帮助我理解之间的区
  • 从 Linux 命令行发送 SNMP 陷阱消息

    Folks 我需要从 Linux 命令行使用此命令 snmptrap 将自定义消息发送到陷阱侦听器 我需要根据用户设置在 v1 和 v2c 中发送相同的消息 这是我发现的 For v1 snmptrap v 1 c Tas hostname
  • Alsa 带有来自调制解调器的 PCM 接口

    我有一个基于 imx28 CPU 的定制板 CPU 的串行端口连接到调制解调器的 PCM 输出 我必须为调制解调器的 PCM 接口开发一个驱动程序 使其成为 ALSA SoC 的一部分 您能指出内核树 中与我的设置重新组合的一些驱动程序吗
  • Linux TCP服务器:在接受连接之前读取客户端的IP地址

    Related C Winsock API如何在接受连接之前获取连接客户端IP https stackoverflow com questions 716209 c winsock api how to get connecting cli
  • 原生 Linux 应用程序可像 ResHacker 一样编辑 Win32 PE

    我想运行自动修改 dll服务 用户提交特定的 dll 我在服务器上修改它 然后用户可以下载 dll的修改版本 是否有任何本机 Linux 应用程序提供常见的 Win32 PE 修改功能 例如图标 字符串 加速器 对话等 至少提供命令行或脚本
  • PHP 静态变量用双引号引起来

    如何让 PHP 计算双引号中的静态变量 我想做这样的事情 log self CLASS METHOD entering 我尝试过各种 组合来获取变量值self CLASS 但没有任何效果 我目前已经解决了字符串连接问题 但输入起来很痛苦 l
  • 退出 bash 脚本但保持进程运行

    我正在运行服务器 需要使用参数执行以下命令 这些脚本目前工作得很好 但问题是当我运行脚本时我无法返回到控制台 它在控制台中保持运行 如果我强行停止它 那么该过程也会停止 我想继续运行该进程并返回到控制台 bin sh php home st
  • 将 stdout 作为命令行 util 的文件名传递?

    我正在使用一个命令行实用程序 该实用程序需要传递文件名以将输出写入 例如 foo o output txt 它唯一写入的东西stdout是一条消息 表明它运行成功 我希望能够通过管道传输写入的所有内容output txt到另一个命令行实用程
  • 在中断时获取 current->pid

    我正在Linux调度程序上写一些东西 我需要知道在我的中断到来之前哪个进程正在运行 当前的结构可用吗 如果我在中断处理程序中执行 current gt pid 我是否可以获得我中断的进程的 pid 你可以 current gt pid存在并
  • 通过 SSH 将变量传递给远程脚本

    我正在通过 SSH 从本地服务器在远程服务器上运行脚本 首先使用 SCP 复制该脚本 然后在传递一些参数时调用该脚本 如下所示 scp path to script server example org another path ssh s
  • 如何在两个不同帐户之间设置无密码身份验证

    我们可以在两台机器的两种不同用途之间设置无密码身份验证吗 例如 计算机A有用户A 计算机B有用户B 我们可以设置密码 ssh 以便计算机 A 上的用户 A 使用其用户帐户 A 登录计算机 B 谢谢你 如果我理解你的问题 你能设置一下吗ssh
  • 如何仅将整个嵌套目录中的头文件复制到另一个目录,在复制到新文件夹后保持相同的层次结构

    我有一个目录 其中有很多头文件 h 和其他 o 和 c 文件以及其他文件 这个目录里面有很多嵌套的目录 我只想将头文件复制到一个单独的目录 并在新目录中保留相同的结构 cp rf oldDirectory newDirectory将复制所有
  • 使用脚本自动输入 SSH 密码

    我需要创建一个自动向 OpenSSH 输入密码的脚本ssh client 假设我需要通过 SSH 进入myname somehost用密码a1234b 我已经尝试过 bin myssh sh ssh myname somehost a123
  • 我应该使用哪个 Linux 发行版作为 Xen 主机? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我为家庭办公室订购了一台服务器 我想用 Xen 对其进行分区 我认为这将使事情保持干净并且更容易维护 我将运行 MySQL PostgreSQL
  • 当库静态链接时静态变量会发生什么

    假设我有图书馆 A 实现单例模式 它的实现中有一个静态变量 A 库被编译为静态库 现在 假设我的项目中有 B 另一个静态链接的静态库 A C 另一个静态链接的静态库 A D 一个顶级程序链接 B and C 最后 我的单例真的是单例 并且我
  • Linux内核页表更新

    在linux x86 中分页 每个进程都有它自己的页面目录 页表遍历从 CR3 指向的页目录开始 每个进程共享内核页目录内容 假设三个句子是正确的 假设某个进程进入内核 模式并更新他的内核页目录内容 地址映射 访问 权利等 问题 由于内核地
  • 进程名称长度的最大允许限制是多少?

    进程名称允许的最大长度是多少 我正在读取进程名称 proc pid stat文件 我想知道我需要的最大缓冲区 我很确定有一个可配置的限制 但就是找不到它在哪里 根据man 2 prctl http man7 org linux man pa

随机推荐