android内核的电源管理(PM)

Android定义了几种低功耗的状态:earlysuspend(挂起早期),suspend(挂起),hibernation(休眠)。之所以增加了节能的复杂性,主要考虑到android设备在有程序运行时同样需要进行节能这种特殊需求,以及考虑了外设(比如wifi、led等)单独节能的需求。

其中earlysuspend是一种低功耗的状态,某些设备可以选择进入某种功耗较低的状态,比如LCD可以降低亮度或灭掉。此状态为android新增状态。

syspend指除电源管理以外的其它外围模块以及cpu均不工作,只有内存保持自刷新的状态。此状态的进入方式android有修改。

Hibernation指所有内存镜像都被写入磁盘中,然后系统关机,恢复后系统能恢复到关机前状态。

电源管理源代码主要在/kernel/power/文件夹下。用户可以通过读写sys文件/sys/power/state实现控制系统进入低功耗状态。用户通过将const char * const pm_states[] 中定义的字符串, 比如“on”对应非节能状态,“mem”,“standby”对应earlysuspend,“disk”对应hibernation,wake lock 机制进入suspend状态。写入/sys/power/state进行功耗控制,会调用到state_store():

static ssize_tstate_store(struct kobject *kobj, struct kobj_attribute *attr,

            const char *buf,size_t n)

{

#ifdef CONFIG_SUSPEND

#ifdefCONFIG_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;

首先判断用户写入的是否是disk字符串,如果是则调用hibernate()函数命令系统进入hibernation状态

/* First, check if we are requested to hibernate */

if (len == 4 && !strncmp(buf, "disk", len)) {

     error = hibernate();

  goto Exit;

}

如果是其他字符串则且定义了CONFIG_EARLYSUSPEND调用request_suspend_state(),如果未定义了CONFIG_EARLYSUSPEND调用enter_state()

#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)

#ifdefCONFIG_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;

}

request_suspend_state()函数是android相对标准linux改动的地方。在标准linux内核中,用户通过 sysfs 写入“mem”和“standby”时,会直接调用enter_state()进入suspend模式,但在android中则会调用request_suspend_state()函数进入early suspend状态。request_suspend_state()函数代码如下:

void request_suspend_state(suspend_state_tnew_state)

{

unsigned long irqflags;

int old_sleep;

 

spin_lock_irqsave(&state_lock, irqflags);

old_sleep = state & SUSPEND_REQUESTED;

if (debug_mask & DEBUG_USER_STATE) {

     struct timespec ts;

     struct rtc_time tm;

     getnstimeofday(&ts);

     rtc_time_to_tm(ts.tv_sec, &tm);

     pr_info("request_suspend_state: %s (%d->%d) at %lld"

         "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",

         new_state != PM_SUSPEND_ON ? "sleep" :"wakeup",

         requested_suspend_state, new_state,

         ktime_to_ns(ktime_get()),<

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值