一、休眠概述
休眠,简而言之就是设施在不须要工作的时候把一些部件、外设关掉 (掉电或让它进入低功耗模式)。
为什么要休眠呢?一言以蔽之:省电。
休眠分被动休眠和被动休眠。被动休眠:比方我电脑不必了,就通过设置让零碎进入休眠模式;被动休眠:零碎检测到本人闲的慌,为了节约故,本人就休眠去了。
二、Android 休眠
休眠是内核的外围工作,而 Android 是基于 Linux 内核的,所以 Android 休眠和内核有着千头万绪的分割;因为 Android 的非凡利用场景:挪动设施,所以 Android 休眠和内核又有着特地的需要。
1、分割:
Android 设施停止使用,零碎没有什么事件可做,进入休眠状态的性能最终是由内核去实现的;每一类硬件都有本人的驱动,具体的驱动决定怎么进入休眠以及处于何种档次的休眠。比方:对于 platform_device,就依照 platform_driver 定义的规定,在 suspend 调用的时候,去做下面提到的事件:
struct platform_driver {int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};
2、Android 的特地需要:
比方对于本人的电脑,不必让它休眠好了;然而对于咱们如影随行的手机,在休眠的时候还要睁一只眼:复电了要告诉你,QQ 啊微信啊什么的由信息了也要告诉你,所以 Android 在 Linux 内核休眠机制之上,提出了“Opportunistic Suspend”。
三、休眠实际
絮絮叨叨这么多,上面让咱们切切实实体验下休眠。
1、休眠模式
休眠是分好几种模式的,不同模式实现形式、耗电量不同,以下来自 Documentation/power/states.txt:
The kernel supports four power management states generically, though
one is generic and the other three are dependent on platform support
code to implement the low-level details for each state.
This file describes each state, what they are
commonly called, what ACPI state they map to, and what string to write
to /sys/power/state to enter that state
state: Freeze / Low-Power Idle
ACPI state: S0
String: "freeze"
This state is a generic, pure software, light-weight, low-power state.
It allows more energy to be saved relative to idle by freezing user
space and putting all I/O devices into low-power states (possibly
lower-power than available at run time), such that the processors can
spend more time in their idle states.
This state can be used for platforms without Standby/Suspend-to-RAM
support, or it can be used in addition to Suspend-to-RAM (memory sleep)
to provide reduced resume latency.
State: Standby / Power-On Suspend
ACPI State: S1
String: "standby"
This state offers minimal, though real, power savings, while providing
a very low-latency transition back to a working system. No operating
state is lost (the CPU retains power), so the system easily starts up
again where it left off.
We try to put devices in a low-power state equivalent to D1, which
also offers low power savings, but low resume latency. Not all devices
support D1, and those that don't are left on.
State: Suspend-to-RAM
ACPI State: S3
String: "mem"
This state offers significant power savings as everything in the
system is put into a low-power state, except for memory, which is
placed in self-refresh mode to retain its contents.
System and device state is saved and kept in memory. All devices are
suspended and put into D3. In many cases, all peripheral buses lose
power when entering STR, so devices must be able to handle the
transition back to the On state.
For at least ACPI, STR requires some minimal boot-strapping code to
resume the system from STR. This may be true on other platforms.
State: Suspend-to-disk
ACPI State: S4
String: "disk"
This state offers the greatest power savings, and can be used even in
the absence of low-level platform support for power management. This
state operates similarly to Suspend-to-RAM, but includes a final step
of writing memory contents to disk. On resume, this is read and memory
is restored to its pre-suspend state.
虽说 kernel 反对上述四种休眠模式,但具体哪几种可用取决于你的硬件。那么怎么晓得本人的 Android 设施反对的休眠模式呢?
答案:通过 /sys/ 文件系统。查问反对的休眠模式能够 cat 文件 /sys/power/state:
cat /sys/power/state
freeze mem
如果咱们往 /sys/power/state 文件 echo 下面的某一种模式的字符串,零碎就会进入相应的休眠模式:
echo "mem" > /sys/power/state
如果你搜寻过 Android 休眠相干的内容,在老版本的 Android(4.4 版本之前)会见有提到 PowerManager 的 setPowerState()办法,该办法即是通过以上形式使零碎进入休眠。但自从引入 Autosleep 后,就不在这么做了,setPowerState()办法也匿影藏形。
2、/sys/power/ 目录下文件
文件简介:
- /sys/power/state:用来控制系统的 Power 状态。读取该文件能够获取零碎反对的休眠模式,写入该文件休眠模式的一种,零碎进入到指定的休眠模式。如上所示例。
- /sys/power/autosleep:从 Android wakelocks 补丁集中演变而来,用于取代 Android wakelocks 中的主动休眠性能。向该文件写入 /sys/power/state 返回值的某一种,零碎会在适当的时候进入指定的休眠的模式;读取该文件返回之前写入的数值。
- /sys/power/wake_lock、/sys/power/wake_unlock:即咱们常说的休眠锁,如果利用持有休眠锁,零碎将无奈进入休眠模式。在 Android wakelocks 时代,写 wake_lock 获取锁,写 wake_unlock 开释锁;在 AutoSleep 时代,具体参见【Android 休眠】之 AutoSleep
- wakeup_count:用于解决“system suspend 和 system wakeup events 之间的同步问题”。
- /sys/power/pm_async:状态切换开关,容许 / 禁止 User 空间对设施进行异步的 suspend 和 resume 操作。
-
/sys/power/pm_freeze_timeout:零碎在执行休眠动作的时候要解冻 (freeze) 用户控件的过程和内核空间的容许解冻的内核线程,执行这些操作要耗时间吧?该文件指定所需工夫的最大值。
四、其余须要明了的问题
1、Android 设施屏幕暗下来的时候,并不是立刻就进入了休眠模式;当所有唤醒源都处于 de-avtive 状态后,零碎才会进入休眠。
2、Android 设施连着 adb 线到其余设施的状况下,设施是不会进入休眠模式的。
3、有休眠操作就有唤醒,就须要唤醒源。唤醒源有很多种,在内核注册,比方罕用的 Power 按键。
4、已经困惑的一个问题:零碎怎么晓得本人应该进入休眠模式了?它的判断根据是什么?
在 wakelock 时代,零碎休眠过程中去检测休眠锁;如果零碎中没有其余部件持有休眠锁,就尝试进入休眠模式,没有异样事件产生的话就进入休眠模式。
Android 从 4.4 开始应用 autosleep 机制,只有不存在任何 active 的唤醒源 (wakeup_source) 了,就进入休眠模式。
5、零碎 Power Manager 整体流程