state 是 sysfs 中一个文件,为 Generic PM
的核心接口,在“kernel/power/main.c”中实现,用于将系统置于指定的 Power State。
读取该文件,返回当前系统支持的 Power State,形式为字符串。在内核中,有两种类型的 Power
State,一种是 Hibernate
相关的,名称为“disk”,除“disk”之外,内核在"/kernel/power/suspend.c"中通过数组的形式定义了另外 3 个
state,如下:
const char *const pm_states[PM_SUSPEND_MAX] = {
[PM_SUSPEND_FREEZE] = "freeze",
[PM_SUSPEND_STANDBY] = "standby",
[PM_SUSPEND_MEM] = "mem",
};
这些 Power State 的解释如下:
写入特定的 Power State 字符串,将会把系统置为该模式。
该接口只和 Sleep 功能有关,因此由“CONFIG_PM_SLEEP”宏定义控制。它的存在,是为了解决
Sleep 和 Wakeup 之间的同步问题。
系统睡眠后,可以通过保留的 Wakeup source 唤醒系统。而在 CPU 体系中,唤醒系统就是唤醒
CPU,而唤醒 CPU 的唯一途径,就是 Wakeup source 产生中断(内核称作 Wakeup event)。而内核要保证在多种状态下,Sleep/Wakeup
的行为都能正常,如下:
▆ 系统处于 sleep 状态时,产生了 Wakeup event。此时应该直接唤醒系统。这没有问题。
▆ 系统在进入 sleep 的过程中,产生了
Wakeup event。此时应该放弃进入 sleep。
这一点就不那么容易做到了。例如,当 Wakeup event
发生在“/sys/power/state”被写之后、内核执行 freeze 操作之前。此时用户空间程序依旧可以处理 Wakeup
event,或者只是部分处理。而内核却以为该 Event 已经被处理,因此并不会放弃此次 sleep 动作。
这就会造成,Wakeup event 发生后,用户空间程序已经后悔了,不想睡了,但最终还是睡下去了。直到下一个
Wakeup event 到来。
为了解决上面的问题,内核提供 wakeup_count 机制,配合“/sys/power/state”,以实现
Sleep 过程中的同步。该机制的操作行为如下:
▆ wakeup_count 是内核用来保存当前
wakeup event 发生的计数。
▆ 用户空间程序在写入
state 切换状态之前,应先读取 wakeup_count 并把获得的 count 写回给 wakeup_count。
▆ 内核会比对写回的 count 和当前的 count 是否一致,如果不一致,说明在读取/写回操作之间,产生了新的的
wakeup event,内核就会返回错误。
▆ 用户空间程序检测到写入错误之后,不能继续后的动作,需要处理响应的 event 并伺机再次读取/写回
wakeup_count。
▆ 如果内核比对一致,会记录 write wakeup_count 成功时的 event 快照,后面继续
suspend 动作时,会检查是否和快照相符,如果不符,会终止 suspend。
▆ 用户空间程序检测到写入正确后,可以继续对 state 的写入,以便发起一次状态切换。而此时是安全的。
全部0条评论
快来发表一下你的评论吧 !