曾经讲过,linux系统里面有两种睡眠模型,如上图所示。所谓系统睡眠模型就是把整个系统陷入休眠,这一节来讲它,以下所有内容都是针对这个模型来讲的;所谓runtime电源管理模型关注于设备的省电。睡眠之后要唤醒,睡眠前的状态是保存在RAM里还是disk(是指flash里)里,有这两种选择,就分出这两种不同的睡眠方式。Standby模式是指把CPU关掉,其他模块还在运行,这种模式下的省电效果并不明显。本节主要讲解suspend to RAM。
如上图所示,Win7下的睡眠就是指suspend to RAM,休眠就是指suspend to disk。Ubunto中,suspend就是指standby,hibernate就是指suspend to disk。
上图为linux系统睡眠和唤醒的大致流程。更详尽的过程如下图所示。对于应用程序来说,只要将一个字符串写入/sys/power/state目录就可以使整个系统进入休眠,唤醒的之后就会重新执行,应用程序感受不到睡眠和唤醒的具体过程,但是写入字符串这个操作会导致内核做了一大堆的事情。
在这张图里,我们只需要关注两点,一个是设备驱动程序相关的,你写的驱动程序如果想实现休眠唤醒的话,必须实现两个函数:suspend和resume。另一个是平台相关的代码,在上一个视频里我们实现的在u-boot里面的休眠和唤醒就属于CPU芯片相关内容。
Linux系统suspend的实现
1. suspend流程:
启动 suspend to ram 的流程:
echo mem > /sys/power/state //往这个文件里写入某个字符串。
Cat /sys/power/state命令可以查看系统支持的休眠方式,写入这两个字符串中的一种时,就会进入对应的休眠方式。既然能够通过写入某个字符串实现睡眠的方式,那就表明虚拟文件state肯定对应着两个函数:读函数和写函数。这两个函数对应kernel/power/main.c下的state_store(写函数),和state_show(读函数),实现对文件state的读和写操作。那么这两个函数怎么跟state文件联系起来呢?是通过main.c下的power_attr(state);。查看power_attr宏的定义如下:
#define power_attr(_name) \
static struct kobj_attribute _name##_attr = { \
.attr = { \
.name = __stringify(_name), \
.mode = 0644, \
}, \
.show = _name##_show, \
.store = _name##_store, \
}
把名字带入如下:
static struct kobj_attribute state_attr = { \
.attr = { \
.name = __stringify("state"), \
.mode = 0644, \
}, \
.show = state_show, \
.store =state_store, \
}
对于state_store函数的调用过程(也就是将一个字符串写入state文件,开启对应睡眠模式的函数调用过程)查看本节资料《电源管理.txt》。
驱动程序里相关的电源管理函数的调用过程:
休眠: prepare—>suspend—>suspend_late—>suspend_noirq
唤醒: resume_noirq—>resume_early—>resume-->complete
参考文章:
实现流程: Linux电源管理(6)_Generic PM之Suspend功能
http://www.wowotech.net/linux_kenrel/suspend_and_resume.html
驱动所涉及的接口: Linux电源管理(4)_Power Management Interface
http://www.wowotech.net/linux_kenrel/pm_interface.html