当前位置:操作系统 > 安卓/Android >>

Android中Linux suspend/resume流程

Android中Linux suspend/resume流程
首先我们从linux kernel 的suspend说起,不管你是使用echo mem > /sys/power/state 或者使用你的开发板已经拥有的power key 都可以实现系统进入suspend的功能,这是suspend的基础,即控制系统使suspend得到执行的机会,这里相信大家都可以理解,不再过多说明。

那么suspend得到了执行的机会又是怎么一步一步开始往下执行的呢?现在就开始我们的系统的电源管理之旅:

我们就通过echo mem > /sys/power/state这种方式来看,这样更容易被理解,位于/sys/power下面的这个state,做driver不知道那可说不过去,我们就看看这个state是在哪个地方创建的吧

kernel/kernel/power/suspend.c

 

[html] view plaincopyprint?
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; 
    return sysfs_create_group(power_kobj, &attr_group); 

 
core_initcall(pm_init); 

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;
 return sysfs_create_group(power_kobj, &attr_group);
}

core_initcall(pm_init);
这段代码很少却很重要,我关心的是他确实为我们在sys目录下先建了一个power目录,然后,return时创建了很多接口,其中一个就是state,以下是接口定义

 

[html] view plaincopyprint?
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_DEBUG 
    &pm_test_attr.attr, 
#endif 
#ifdef CONFIG_USER_WAKELOCK 
    &wake_lock_attr.attr, 
    &wake_unlock_attr.attr, 
#endif 
#endif 
    NULL, 
}; 
 
static struct attribute_group attr_group = { 
    .attrs = g, 
}; 

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_DEBUG
 &pm_test_attr.attr,
#endif
#ifdef CONFIG_USER_WAKELOCK
 &wake_lock_attr.attr,
 &wake_unlock_attr.attr,
#endif
#endif
 NULL,
};

static struct attribute_group attr_group = {
 .attrs = g,
};上面你可以看到了这些接口了

我们在echo mem > /sys/power/state,或调用的我们的接口函数state_store,suspend也就才真正开始走出第一步


[html] view plaincopyprint?
static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, 
               const char *buf, size_t n) 

#ifdef CONFIG_SUSPEND 
#ifdef CONFIG_EARLYSUSPEND 
    suspend_state_t state = PM_SUSPEND_ON; 
#else 
    suspend_state_t state = PM_SUSPEND_STANDBY; 
#endif 
    const char * const *s; 
#endif 
    char *p; 
    int len; 
    int error = -EINVAL; 
 
    p = memchr(buf, '\n', n); 
    len = p ? p - buf : n; 
 
    /* First, check if we are requested to hibernate */ 
    if (len == 4 && !strncmp(buf, "disk", len)) { 
        error = hibernate(); 
                goto Exit; 
    } 
 
#ifdef CONFIG_SUSPEND 
    for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { 
        if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) 
            break; 
    } 
    if (state < PM_SUSPEND_MAX && *s) 
#ifdef CONFIG_EARLYSUSPEND 
        if (state == PM_SUSPEND_ON || valid_state(state)) { 
            error = 0; 
            request_suspend_state(state); 
        } 
#else 
        error = enter_state(state); 
#endif 
#endif 
 
 Exit: 
    return error ? error : n; 

static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
      const char *buf, size_t n)
{
#ifdef CONFIG_SUSPEND
#ifdef CONFIG_EARLYSUSPEND
 suspend_state_t state = PM_SUSPEND_ON;
#else
 suspend_state_t state = PM_SUSPEND_STANDBY;
#endif
 const char * const *s;
#endif
 char *p;
 int len;
 int error = -EINVAL;

 p = memchr(buf, '\n', n);
 len = p ? p - buf : n;

 /* First, check if we are requested to hibernate */
 if (len == 4 && !strncmp(buf, "disk", len)) {
  error = hibernate();
                goto Exit;
 }

#ifdef CONFIG_SUSPEND
 for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
  if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
   break;
 }
 if (state < PM_SUSPEND_MAX && *s)
#ifdef CONFIG_EARLYSUSPEND
  if (state == PM_SUSPEND_ON || valid_state(state)) {
   error = 0;
   request_suspend_state(state);
  }
#else
  error = enter_state(state);
#endif
#endif

 Exit:
 return error ? error : n;
}这里我们echo mem > /sys/power/state, 还有一种echo on > /sys/power/state,接着state_store进入reauest_suspend_state(state),然后如果是on的话进入late_resume_work(在执行late_resume_work之前会向系统申请main_wake_lock),如果是mem进入early_suspend_work。

reauest_suspend_state函数路径:kernel/kernel/power/earlysuspend.c

 

补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,