2024年3月9日发(作者:)
第十三章 Android内核驱动——电源管理
13.1 基本原理
Android 中定义了几种低功耗状态:earlysuspend,suspend,hibernation。
earlysuspend是一种低功耗的状态,某些设备可以选择进入某种功耗较低的状态,比如
LCD可以降低亮度或灭掉;
suspend是指除电源管理以外的其他外围模块以及cpu均不工作,只有内存保持自刷新的
状态;
hibernation是指所有内存镜像都被写入磁盘中,然后系统关机,恢复后系统将能恢复到
“关机”之前的状态。
13.2 电源管理机制的实现
电源管理机制的源代码主要在kernel/power/文件夹下面。
main.c文件是整个框架的入口。用户可以通过读写sys文件/sys/power/state实现控制系统进
入低功耗状态。用户对于/sys/power/state的读写会调用到main.c中的state_store(),用户可
以写入const char * const pm_states[] 中定义的字符串, 比如“on”,“mem”,“standby”,
“disk”。
state_store()首先判断用户写入的是否是“disk”字符串,如果是则调用hibernate()函数命令
系统进入hibernation状态。如果是其他字符串则调用request_suspend_state()(如果未定义
CONFIG_EARLYSUSPEND)或者调用enter_state()(如果未定义CONFIG_EARLYSUSPEND)。
request_suspend_state()函数是android相对标准linux改动的地方,它实现在earlysuspend.c
中。在标准linux内核中,用户通过 sysfs 写入“mem”和“standby”时,会直接调用enter_state()
进入suspend模式,但在android中则会调用request_suspend_state()函数进入early suspend
状态。request_suspend_state()函数代码如下:
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);
}
Linux公社() 是包括Ubuntu,Fedora,SUSE技术,最新IT资讯等Linux专业类网站。
requested_suspend_state = new_state;
spin_unlock_irqrestore(&state_lock, irqflags);
}
early_suspend_work和late_resume_work定义为
static DECLARE_WORK(early_suspend_work, early_suspend);
static DECLARE_WORK(late_resume_work, late_resume);
可见实际工作的是early_suspend和late_resume这两个函 数。Android提供了
register_early_suspend和unregister_early_suspend两个函数供驱动调用,分别完成设备
earlysuspend的注册和注销。系统将所有注册支持early_suspend的设备驱动对应的 handler
挂在一个称为early_suspend_handler的链表上。函数early_suspend和late_resume完成的事
情很简单,就是遍历这个链表,依次调用每个设备注册的handler,late_resume是唤醒处于
early_suspend的那些设备。代码如下:
static void early_suspend(struct work_struct *work)
{
struct early_suspend *pos;
unsigned long irqflags;
int abort = 0;
mutex_lock(&early_suspend_lock);
spin_lock_irqsave(&state_lock, irqflags);
if (state == SUSPEND_REQUESTED)
state |= SUSPENDED;
else
abort = 1;
spin_unlock_irqrestore(&state_lock, irqflags);
if (abort) {
if (debug_mask & DEBUG_SUSPEND)
pr_info("early_suspend: abort, state %dn", state);
mutex_unlock(&early_suspend_lock);
goto abort;
}
if (debug_mask & DEBUG_SUSPEND)
pr_info("early_suspend: call handlersn");
//遍历链表依次调用每个驱动的 handler
list_for_each_entry(pos, &early_suspend_handlers, link) {
if (pos->suspend != NULL)
pos->suspend(pos);
}
mutex_unlock(&early_suspend_lock);
if (debug_mask & DEBUG_SUSPEND)
pr_info("early_suspend: syncn");
//同步文件系统
sys_sync();
abort:
spin_lock_irqsave(&state_lock, irqflags);
if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
wake_unlock(&main_wake_lock);
spin_unlock_irqrestore(&state_lock, irqflags);
}
static void late_resume(struct work_struct *work)
{
struct early_suspend *pos;
unsigned long irqflags;
int abort = 0;
mutex_lock(&early_suspend_lock);
spin_lock_irqsave(&state_lock, irqflags);
if (state == SUSPENDED)
state &= ~SUSPENDED;
Linux公社() 是包括Ubuntu,Fedora,SUSE技术,最新IT资讯等Linux专业类网站。


发布评论