电源管理基本观念之一
2019-07-14 01:48 发布
生成海报
1.Linux 描述的电源状态
- On(on) S0
- Working
- Standby (standby) S1
- CPU and RAM are powered but not executed
- Suspend to RAM(mem) S3
- RAM is powered and the running content is saved to RAM
- Suspend to Disk,Hibernation(disk) S4 - All content is saved to Disk and power
down
S3 aka STR(suspend to ram),挂起到内存,简称待机。计算机将目前的运行状态等数据存放在内存,关闭硬盘、外设等设备,进入等待状态。此时内存仍然需要电力维持其数据,但整机耗电很少。恢复时计算机从内存读出数据,回到挂起前的状态,恢复速度较快。对DDR的耗电情况进行优化是S3性能的关键,大多数手持设备都是用S3待机。
S4 aka STD(suspend to disk),挂起到硬盘,简称休眠。把运行状态等数据存放在硬盘上某个文件或者某个特定的区域,关闭硬盘、外设等设备,进入关机状态。此时计算机完全关闭,不耗电。恢复时计算机从休眠文件/分区中读出数据,回到休眠前的状态,恢复速度较慢。电子书项目中,见过一款索尼的电子书,没有定义关机状态,只定义了S4,从而提高开机速度。
2.Linux内核电源管理接口
Linux把电源接口框架纳入设备模型中,通过power_kobj对象的属性文件提供操作电源策略的接口。
[cpp] view plain copy print ?
static int __init pm_init( void )
{
int error = pm_start_workqueue();
if (error)
return error;
hibernate_image_size_init();
hibernate_reserved_size_init();
power_kobj = kobject_create_and_add("power" , NULL);
if (!power_kobj)
return -ENOMEM;
error = sysfs_create_group(power_kobj, &attr_group);
if (error)
return error;
return pm_autosleep_init();
}
power_kobj的属性都定义在attr_group中,每一个属性文件都有对应的一组show和store方法。
[cpp] view plain copy print ?
static struct attribute * g[] = {
&state_attr.attr,
#ifdef CONFIG_PM_TRACE
&pm_trace_attr.attr,
&pm_trace_dev_match_attr.attr,
#endif
#ifdef CONFIG_PM_SLEEP
&pm_async_attr.attr,
&wakeup_count_attr.attr,
#ifdef CONFIG_PM_AUTOSLEEP
&autosleep_attr.attr,
#endif
#ifdef CONFIG_PM_WAKELOCKS
&wake_lock_attr.attr,
&wake_unlock_attr.attr,
#endif
#ifdef CONFIG_PM_DEBUG
&pm_test_attr.attr,
#endif
#endif
NULL,
};
static struct attribute_group attr_group = {
.attrs = g,
};
从代码可以看出来,state属性是主属性文件,必须具备,其他属性文件都有相应的宏开关,根据需要定制。
3. 电源状态切换(state属性文件)
Linux的世界里,一切皆文件。state属性用来在S0,S1,S3,S4四种不同的电源状态之间切换。通过向state文件中写入不同的值来让系统进入不同的电源状态。接收状态值的函数是state_store。
[cpp] view plain copy print ?
static ssize_t state_store( struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
{
suspend_state_t state;
int error;
error = pm_autosleep_lock();
if (error)
return error;
if (pm_autosleep_state() > PM_SUSPEND_ON) {
error = -EBUSY;
goto out;
}
state = decode_state(buf, n);
if (state < PM_SUSPEND_MAX)
error = pm_suspend(state);
else if (state == PM_SUSPEND_MAX)
error = hibernate();
else
error = -EINVAL;
out:
pm_autosleep_unlock();
return error ? error : n;
}
autosleep是android内核为了跟主线内核兼容所引入的。切换电源状态的入口函数是pm_suspend。针对嵌入式系统,S3是一种比较常用的节电状态。俗称待机。待机过程可以粗略的分为五个阶段,但不一定有严格的界限。
a)冻结用户态进程
b)挂起设备
c)针对soc相应的节电操作和为唤醒做准备工作
d)smp中非启动cpu的挂起
e)cpu core的挂起
3.1
冻结用户进程
进程冻结模块由CONFIG_FREEZER宏开关控制。
相关代码在kernel/power/process.c中,程序的结构比较简洁,总共就五个函数。
freeze process的控制过程都在freeze_processes函数中
[plain] view plain copy print ?
int freeze_processes(void)
{
int error;
error = __usermodehelper_disable(UMH_FREEZING);
if (error)
return error;
if (!pm_freezing)
atomic_inc(&system_freezing_cnt);
printk("Freezing user space processes ... ");
pm_freezing = true;
error = try_to_freeze_tasks(true);
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮