睡眠过程:
入口:用户空间的代码通过向/sys/power/state文件节点写入特定的字符串(on/mem)来请求系统进入特定的状态,
过程:
1) 向/sys/power/state文件写入时会调用到state_store函数:
state() { #ifdef CONFIG_EARLYSUSPEND request_suspend_state(state) #else pm_suspend(state); #endif }
如果配置了early_suspend选项,则调用request_suspend_state去执行android的suspend过程
2) request_suspend_state会调用queue_up_early_suspend_work函数向early_suspend_wq工作队列中提交一个名叫early_suspend_work的工作,其对应的工作函数为
static void early_suspend(struct work_struct *work) { list_for_each_entry(pos, &early_suspend_handlers, link) { if (pos->suspend != NULL) pos->suspend(pos); } queue_work(suspend_wq, &suspend_work); }
首先会调用驱动注册的early_suspend的回调函数,一般背光和LCD等会注册这些回调函数,可以保证系统还没有进入休眠状态的时候下电,起到更加省电的目的,
然后向suspend_wq工作队列中提交一个名为suspend_work的工作,其对应的工作函数为
static void try_to_suspend(struct work_struct *work) { pm_suspend(suspend_state) }
static int enter_state(suspend_state_t state) { if (!mutext_trylock(&pm_mutex)) return -EBUSY; printk(KERN_INFO "PM: Syncing filesystems..."); 1> if (!suspend_sync()) { printk(KERN_INFO "PM:Suspend aborted for filesystem syncing\n"); error = -EBUSY; goto Unlock; } 2> error = suspend_prepare(); -->suspend_freeze_process(); if (error) goto Unlock; 3> error = suspend_devices_and_enter(state); -->dpm_suspend_start(PMSG_SUSPEND) //执行驱动的prepare和suspend回调 -->dpm_prepare(PMSG_SUSPEND); -->while(!list_empty(&dpm_list)) { struct device *dev = to_device(dpm_list.next); //从头到尾扫描 device_prepare(dev, state); //执行驱动的prepare回调函数.将device挂到dpm_prepared_list链表尾部 if (!list_empty(&dev->power.entry)) list_move_add_tail(&dev->power.entry, &dpm_prepared_list); } -->dpm_suspend(PMSG_SUSPEND); -->while (!list_empty(&dpm_prepared_list)) { struct device *dev = to_device(dpm_prepared_list.prev); //从尾到头扫描,即子设备先挂起 device_suspend(dev); //执行驱动的suspend回调函数 if (!list_empty(&dev->power.entry)) list_move(&dev->power.entry, &dpm_suspended_list); //将device挂到dpm_suspended_list头部。 } -->suspend_enter(state, &wakeup) -->dpm_suspend_end(PMSG_SUSPEND); //执行驱动的suspend_late和suspend_noirq回调函数 -->dpm_suspend_late(state); //和dpm_suspend类似,从尾到头扫描dpm_suspended_list上的设备, 并执行驱动的suspend_late回调函数,然后将设备挂到dpm_late_early_list链表的头部。 -->dpm_suspend_noirq(state); -->suspend_device_irqs(); //屏蔽所有设备中断,从尾到头扫描dpm_late_early_list上的 -->device_suspend_noirq() //设备,然后挂到dpm_noirq_list链表头部。 -->dpm_resume_end(PMSG_RESUME) Finish: pr_debug(PM: Finishing wakeup.\n"); suspend_finish(); mutex_unlock(&pm_mutex); }
这里分为三个过程:
1>同步文件系统,也就是把脏数据写到磁盘上
2>冻结用户进程和内核线程
3>设备休眠,cpu休眠
详细过程以后再分析。。。