Chinaunix首页 | 论坛 | 博客
  • 博客访问: 244217
  • 博文数量: 18
  • 博客积分: 445
  • 博客等级: 下士
  • 技术积分: 270
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-28 13:59
文章分类

全部博文(18)

文章存档

2013年(2)

2012年(16)

分类:

2012-05-21 15:15:48

原文地址:Android.linux电源管理 作者:public_wds

  设备电源管理两种模型1.系统睡眠模型 2. Runtime电源管理模型。
  子系统和驱动程序的设备电源管理操作都定义在dev_pm_ops中 include/linux/pm.h
suspend dev->class->pm.suspend(dev);dev->type->pm.suspend(dev);dev->bus->pm.suspend(dev).
resume  dev->bus->pm.suspend(dev);dev->type->pm.suspend(dev);dev->class->pm.suspend(dev).
prepare 阶段只使用了bus的回调
complete阶段只使用了bus的回调
main.c是整个框架的入口
# echo mem >/sys/power/state  使系统进行睡眠
# echo on >/sysy/power/state 使系统从睡眠唤醒过来
Android在原有基础上增加了三个机制
wake_lock 唤醒锁机制
Early_suspend 预挂起机制
Last_Resume 迟唤醒机制

在linux中休眠主要分为三个步骤:(1) 冻结用户态进程和内核态状态
(2) 调用注册设备的suspend的回调函数,其调用顺序是按照驱动加载注册顺序。
(3) 休眠核心设备使CPU进入休眠态,冻结进程是内核把进程列表中所有的进程的状态都设置为停止,并且保存下所有进程的上下文。当这些进程被解冻的时候,它们不知道自己被冻结过,只是简单的继续运行。

Android的基本原理如下:当启动一个应用程序的时候,它都可以申请一个wake_lock唤醒锁,每当申请成功之后都会在内核注册一下,当应用程序在某种情况下释放wake_lock的时候,会注销之前申请的wake_lock。系统只要有一个wake_lock,系统就不能睡眠,但此时各模块可以进行early_suspend在系统启动的时候会创建一个主唤醒锁main_wake_lock ,该锁是内核初始化并持有的一个WAKE_LOCK_SUSPEND属性的非限时唤醒锁。 因此,系统正常工作时,将始终因为该锁被内核持有而无法进入睡眠状态,也就是说不添加新锁的情况下,只需将main_wake_lock解锁,系统即可进入睡眠状态。


电源管理的机制的源代码主要在/kernel/power 下 函数early_suspend和late_resume完场的事情很简单,就是遍历这个链表,依次调用每个设备注册的handler。late_resume是唤醒处于early_suspend的那些设备。  list_for_each_entry(pos,&early_suspend_handlers,link)void request_suspend_state(suspend_state_t new_state)
{
    unsigned long irqflags;
    int old_sleep;
    spin_lock_irqsave(&state_lock, irqflags);
    old_sleep = state & SUSPEND_REQUESTED;
    ......
    if (!old_sleep && new_state != PM_SUSPEND_ON) {
         state |= SUSPEND_REQUESTED;
            //判断是否为省电请求,如果是排队一个 early_suspend_work
           queue_work(suspend_work_queue, &early_suspend_work);
    } else if (old_sleep && new_state == PM_SUSPEND_ON) {
         state &= ~SUSPEND_REQUESTED;
         wake_lock(&main_wake_lock);
        //否则,是唤醒请求,排队 late_resume_work
         queue_work(suspend_work_queue, &late_resume_work);
    }
requested_suspend_state = new_state;
    spin_unlock_irqrestore(&state_lock, irqflags);
}

early_suspend_work 和late_resume_work 定义为 Android 改动较大的另一处是增加了wakelock 机制。实现在wakelock.c 和userwakelock.c 中。
wakelock 可以阻止处于正常运行(active)或者空闲(idle)状态的系统进入睡眠等低功耗状
态。直到所持有的wakelock 全部被释放,系统才能进入睡眠等低功耗的状态。

wakelock 有加锁和解锁两种状态,加锁的方式有两种,一种是永久的锁住,这样的锁除非显
示的放开,是不会解锁的。第二种是超时锁,这种锁会锁定系统一段时间,如果这个时间过
去了,这个锁会自动解除。


Android 使用两条双向链表active_wake_locks[WAKE_LOCK_TYPE_COUNT]分别保存处于active
状态的suspend lock 和 idle lock;使用一条链表inactive_locks 记录所有处于inactive 状态的锁。
锁。

在系统启动的时候,会调用wakelocks_init 函数来完成wakelock  的初始化,但别的驱动程序
也可以再单独创建自用的wakelock,这里初始化的是系统默认的wake lock  以及该机制依赖
的功能。

static DECLARE_WORK(early_suspend_work, early_suspend);
static DECLARE_WORK(late_resume_work, late_resume);
android 中则会调用request_suspend_state()函数进入early suspend状态。


Android的省电模式只有suspend和earlysuspend。
early suspend是假睡眠,cpu仍然工作,并没有通过pmu。


suspend 函数完成suspend系统的任务,它是suspend_work这个工作的处理函数,suspend_work排列到suspend_work_queue工作队列中,最终系统会处理这个work,调用其handler即suspend 该函数首先sync文件系统,然后调用pm_suspend(request_suspend_state),接下来pm_suspend就会调用enter_state来进入linux的suspend流程。

 
阅读(1733) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~