****************************************************
作者:Sean
日期:2012-11-29
修改历史:
****************************************************
标准linux休眠过程:
l
l
l
l
l
l
l
l
l
标准linux唤醒过程:
l
l
l
l
l
l
用户可以通过sys文件系统控制系统进入休眠一些BUS
l
查看系统支持的休眠方式:
#cat 常见有standby(suspend
通过
#echo on
>
Android休眠与唤醒
android是在传统的linux内核电源管理设计的基础上,结合手机设计的实际需求而进化出的一套电源管理系统,其核心内容有:wakelock
wakelock在Android的电源管理系统中扮演一个核心的角色。wakelock是一种锁的机制,
当系统在启动完毕后,会自己去加一把名为“main“的锁,而当系统有意愿去睡眠时则会先去释放这把“main”锁,在android中,在early_suspend的最后一步会去释放“main”锁(wake_unlock: 它的缺点是,如果有某一应用获锁而不释放或者因一直在执行某种操作而没时间来释放的话,则会导致系统一直进入不了睡眠状态,功耗过大。
early_suspend:先与linux内核的睡眠过程被调用。一般在手机系统的设计中对背光的操作等采用此类方法,因为背光需要的能耗过大。当然此操作与late_resume是配套使用的。一些在内核中要预先进行处理的事件可以先注册上early_suspend函数,当系统要进入睡眠之前会首先调用这些注册的函数。
本文中,linux 与android休眠唤醒主要相关的文件主要有:
l
l
l
l
l
l
Android
当用户读写/sys/power/state时,linux_source/kernel/power/main.c中的state_store()函数会被调用。其中,android的early_suspend会执行request_suspend_state(state);
static
{
#ifdef
#ifdef
suspend_state_t #else
suspend_state_t #endif
const #endif
char
int
int
p
len
if
error
}
#ifdef
for
if break; }
if
#ifdef
if
error request_suspend_state(state); } #else #endif #endif
return }
在request_suspend_state(state)函数中,会调用early_suspend_work的工作队列,从而进入early_suspend()函数中。
static
void {
unsigned
int
spin_lock_irqsave(&state_lock,
old_sleep
if
struct
struct getnstimeofday(&ts);
rtc_time_to_tm(ts.tv_sec,
pr_info("request_suspend_state:
"(%d-d-d
new_state
requested_suspend_state, ktime_to_ns(ktime_get()),
tm.tm_year
tm.tm_hour, }
if
state
queue_work(suspend_work_queue,
}
state wake_lock(&main_wake_lock);
queue_work(suspend_work_queue, }
requested_suspend_state
spin_unlock_irqrestore(&state_lock, }
在early_suspend()函数中,首先要判断当前请求的状态是否还是suspend,若不是,则直接退出了;若是,函数会调用已经注册的early_suspend的函数。然后同步文件系统,最后释放main_wake_lock。
static {
struct
unsigned
int
mutex_lock(&early_suspend_lock);
spin_lock_irqsave(&state_lock,
if
state else
abort
spin_unlock_irqrestore(&state_lock,
if
if
pr_info("early_suspend: mutex_unlock(&early_suspend_lock);
goto }
if
pr_info("early_suspend:
list_for_each_entry(pos,
if pos->suspend(pos); } mutex_unlock(&early_suspend_lock);
if
pr_info("early_suspend:
sys_sync(); abort:
spin_lock_irqsave(&state_lock,
if wake_unlock(&main_wake_lock);
spin_unlock_irqrestore(&state_lock, }
在wake_unlock()中,删除链表中wake_lock节点,判断当前是否存在wake_lock,若wake_lock的数目为0,则调用工作队列suspend_work,进入suspend状态。
static
void {
int
unsigned
spin_lock_irqsave(&list_lock,
type
#ifdef
wake_unlock_stat_locked(lock, #endif
if
pr_info("wake_unlock:
lock->flags list_del(&lock->link);
list_add(&lock->link,
if
long
if
if
pr_info("wake_unlock:
"%ld\n",
mod_timer(&expire_timer,
}
if
if
pr_info("wake_unlock:
"timer\n",
if
queue_work(suspend_work_queue, }
if
if print_active_locks(WAKE_LOCK_SUSPEND);
#ifdef update_sleep_wait_stats_locked(0); #endif } }
spin_unlock_irqrestore(&list_lock, }
在suspend()函数中,先判断当前是否有wake_lock,若有,则退出;然后同步文件系统,最后调用pm_suspend()函数。
static {
int
int
if
if
pr_info("suspend: return; }
entry_event_num sys_sync();
if
pr_info("suspend:
ret
if
struct
struct getnstimeofday(&ts);
rtc_time_to_tm(ts.tv_sec,
pr_info("suspend:
"(%d-d-d
tm.tm_year
tm.tm_hour, }
if
if
pr_info("suspend:
wake_lock_timeout(&unknown_wakeup, } }
在pm_suspend()函数中,enter_state()函数被调用,从而进入标准linux休眠过程。
int {
if
return
return }
在enter_state()函数中,首先检查一些状态参数,再同步文件系统,然后调用suspend_prepare()来冻结进程,最后调用suspend_devices_and_enter()让外设进入休眠。
static {
int
if
return
if
return
printk(KERN_INFO sys_sync(); printk("done.\n");
pr_debug("PM:
error
if
goto
if
goto
pr_debug("PM:
error
pr_debug("PM: suspend_finish();
mutex_unlock(&pm_mutex);
return }
在suspend_prepare()函数中,先通过pm_prepare_console();给suspend分配一个虚拟终端来输出信息,再广播一个系统进入suspend的通报,关闭用户态的helper进程,然后调用suspend_freeze_processes()来冻结进程,最后会尝试释放一些内存。
static {
int
unsigned
if
return
pm_prepare_console();
error
if
goto
error
if
goto
if
error
goto }
free_pages
if
pr_debug("PM:
shrink_all_memory(FREE_PAGE_NUMBER
if
error
printk(KERN_ERR } }
if
return
suspend_thaw_processes(); usermodehelper_enable();
pm_notifier_call_chain(PM_POST_SUSPEND); pm_restore_console();
return } |
|
来自: linux_android > 《睡眠唤醒》