原文链接:Linux电源管理(6)_Generic PM之挂起功能
1.前言
Linux内核提供了三种暂停方式:Freeze,Standby和STR(暂停到RAM),在用户空间向” / sys / power / state”文件分别写入“ freeze”,“ standby”和“ mem”,可以触发。
另外内核中,挂起和恢复过程涉及到PM核心,设备PM,各个设备的驱动,平台相关的PM,CPU控制等多个模块,涉及控制台切换,进程冻结,CPU热插拔,唤醒处理等过个知识点。就让我们跟着内核代码,一一见识它们吧。

2.暂停功能有关的代码分布
内核中止功能相关的代码包括PM内核,设备PM,平台PM等几大块,具体如下:
1)PM核心
内核/电源/main.c----提供用户空间接口(/ sys /电源/状态)
kernel / power / suspend.c ----挂起功能的主逻辑
内核/电源/suspend_test.c----挂起功能的测试逻辑
内核/电源/控制台.c ----挂起过程中对控制台的处理逻辑
内核/电源/进程.c ----挂起过程中对进程的处理逻辑
2)平台相关的PM
include / linux / suspend.h ----定义平台相关的PM有关的操作函数集
arch / xxx / mach-xxx / xxx.c或者
arch / xxx / plat-xxx / xxx.c ----平台相关的电源管理操作
3.暂停和恢复过程概述
下面的图片对Linuxsuspend&resume过程由一个概述,读者可以顺着这个流程阅读内核源代码。具体的说明,可以参考后面的代码分析。

4.代码分析
4.1暂停入口
在用户空间执行如下操作:
回声“冻结”> / sys / power / state
回声“待机”> / sys / power / state
回声“内存”> / sys / power / state
会通过sysfs触发suspend的执行,相应的处理代码如下:
static ssize_t state_store(struct kobject *kobj,struct kobj_attribute *attr,const char *buf,size_t n){suspend_state_t state;int error;// 1. 获取自动睡眠锁error = pm_autosleep_lock();if (error)return error;// 2. 检查当前是否已处于非ON状态(禁止重复操作)if (pm_autosleep_state() > PM_SUSPEND_ON) {error = -EBUSY;goto out;}// 3. 解析输入状态并执行对应操作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:// 4. 释放锁并返回结果pm_autosleep_unlock();return error ? error : n;}power_attr (状态);
power_attr定义了一个名称为状态的属性文件,该文件的存储接口为state_store,该接口在锁定住自动休眠功能后,解析用户传入的缓冲器(冷冻,备用或MEM),转换成状态参数。
状态参数的类型为suspend_state_t,在包括\ linux \ suspend.h中定义,为电源管理状态在内核中的表示。具体如下:
typedef int __suspend_state_t;#define PM_SUSPEND_ON ((__force suspend_state_t)0)#define PM_SUSPEND_FREEZE ((__force suspend_state_t)1)#define PM_SUSPEND_STANDBY ((__force suspend_state_t)2)#define PM_SUSPEND_MEM ((__force suspend_state_t)3)#define PM_SUSPEND_MIN PM_SUSPEND_FREEZE#define PM_SUSPEND_MAX ((__force suspend_state_t)4)
根据状态的值,如果不是(PM_SUSPEND_MAX,对应于hibernate功能),则调用pm_suspend接口,进行后续的处理。
pm_suspend在内核/power/suspend.c定义,处理所有的suspend过程。
4.2 pm_suspend&enter_state
pm_suspend的实现非常简单,简单的做一下参数合法性判断,直接调用enter_state接口
int pm_suspend(suspend_state_t state){int error;// 1. 检查状态有效性if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)return -EINVAL;// 2. 进入挂起状态error = enter_state(state);// 3. 更新统计信息if (error) {suspend_stats.fail++;dpm_save_failed_errno(error);} else {suspend_stats.success++;}return error;}
enter_state代码为:
static int enter_state(suspend_state_t state){int error;// 1. 检查状态有效性if (!valid_state(state))return -ENODEV;// 2. 获

最低0.47元/天 解锁文章
1317

被折叠的 条评论
为什么被折叠?



