电源管理基本观念之一

2019-07-14 01:48发布

转载:http://blog.sina.com.cn/s/blog_a6559d920101i52j.html

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 plaincopyprint?
  1. static int __init pm_init(void 
  2.  
  3.     int error pm_start_workqueue();  
  4.     if (error)  
  5.         return error;  
  6.     hibernate_image_size_init();  
  7.     hibernate_reserved_size_init();  
  8.     power_kobj kobject_create_and_add("power"NULL);  
  9.     if (!power_kobj)  
  10.         return -ENOMEM;  
  11.     error sysfs_create_group(power_kobj, &attr_group);  
  12.     if (error)  
  13.         return error;  
  14.     return pm_autosleep_init();  
  15.  
power_kobj的属性都定义在attr_group中,每一个属性文件都有对应的一组show和store方法。 [cpp] view plaincopyprint?
  1. static struct attribute g[]  
  2.     &state_attr.attr,  
  3. #ifdef CONFIG_PM_TRACE  
  4.     &pm_trace_attr.attr,  
  5.     &pm_trace_dev_match_attr.attr,  
  6. #endif  
  7. #ifdef CONFIG_PM_SLEEP  
  8.     &pm_async_attr.attr,  
  9.     &wakeup_count_attr.attr,  
  10. #ifdef CONFIG_PM_AUTOSLEEP  
  11.     &autosleep_attr.attr,  
  12. #endif  
  13. #ifdef CONFIG_PM_WAKELOCKS  
  14.     &wake_lock_attr.attr,  
  15.     &wake_unlock_attr.attr,  
  16. #endif  
  17. #ifdef CONFIG_PM_DEBUG  
  18.     &pm_test_attr.attr,  
  19. #endif  
  20. #endif  
  21.     NULL,  
  22. };  
  23.   
  24. static struct attribute_group attr_group  
  25.     .attrs g,  
  26. };  
从代码可以看出来,state属性是主属性文件,必须具备,其他属性文件都有相应的宏开关,根据需要定制。

3. 电源状态切换(state属性文件)

Linux的世界里,一切皆文件。state属性用来在S0,S1,S3,S4四种不同的电源状态之间切换。通过向state文件中写入不同的值来让系统进入不同的电源状态。接收状态值的函数是state_store。 [cpp] view plaincopyprint?
  1. static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,  
  2.                const char *buf, size_t n)  
  3.  
  4.     suspend_state_t state;  
  5.     int error;  
  6.   
  7.     error pm_autosleep_lock();  
  8.     if (error)  
  9.         return error;  
  10.   
  11.     if (pm_autosleep_state() PM_SUSPEND_ON)  
  12.         error -EBUSY;  
  13.         goto out;  
  14.      
  15.   
  16.     state decode_state(buf, n);  
  17.     if (state PM_SUSPEND_MAX)  
  18.         error pm_suspend(state);  
  19.     else if (state == PM_SUSPEND_MAX)  
  20.         error hibernate();  
  21.     else  
  22.         error -EINVAL;  
  23.   
  24.  out:  
  25.     pm_autosleep_unlock();  
  26.     return error error n;  
  27.  
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 plaincopyprint?
  1. int freeze_processes(void)  
  2.  
  3.     int error;  
  4.   
  5.     error __usermodehelper_disable(UMH_FREEZING);  
  6.     if (error)  
  7.         return error;  
  8.   
  9.     if (!pm_freezing)  
  10.         atomic_inc(&system_freezing_cnt);  
  11.   
  12.     printk("Freezing user space processes ... ");  
  13.     pm_freezing true;  
  14.     error try_to_freeze_tasks(true);