android 睡眠和唤醒过程

时间:2023-02-12 14:32:43

睡眠过程:

入口:用户空间的代码通过向/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)
}



3) pm_suspend函数会调用enter_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休眠


详细过程以后再分析。。。