android 休眠唤醒机制分析(三) — suspend

2019-07-14 02:00发布

前面我们分析了休眠的第一个阶段即浅度休眠,现在我们继续看休眠的第二个阶段 — 深度休眠。在深度休眠的过程中系统会首先冻结所有可以冻结的进程,然后依次挂起所有设备的电源,挂起顺序与设备注册的顺序相反,这样保证了设备之间电源的依赖性;直至最后进入省电模式,等待用户或者RTC唤醒;在唤醒过程中则会按照设备注册的顺序依次恢复每个设备的电源进入正常工作状态,解冻相关的进程,然后再进行浅度休眠的唤醒流程。 1、深度休眠入口 根据wake_lock一节的分析我们知道driver层进入深度休眠的入口有4个,分别为expire_timer、wake_lock、wake_lock_timeout、wake_unlock,这几个入口函数将根据相应的条件启动suspend_work里面的pm_suspend()函数进入深度休眠流程,代码在linux/kernel/power/suspend.c中: [cpp] view plaincopy
  1. // 进入深度休眠流程  
  2. int enter_state(suspend_state_t state)  
  3. {  
  4.     int error;  
  5.     // 判断平台是否支持该状态  
  6.     if (!valid_state(state))  
  7.         return -ENODEV;  
  8.   
  9.     if (!mutex_trylock(&pm_mutex))  
  10.         return -EBUSY;  
  11.     // 同步缓存  
  12.     printk(KERN_INFO "PM: Syncing filesystems ... ");  
  13.     sys_sync();  
  14.     printk("done. ");  
  15.   
  16.     pr_debug("PM: Preparing system for %s sleep ", pm_states[state]);  
  17.     // 做好休眠准备  
  18.     error = suspend_prepare();  
  19.     if (error)  
  20.         goto Unlock;  
  21.     // suspend_test  
  22.     if (suspend_test(TEST_FREEZER))  
  23.         goto Finish;  
  24.   
  25.     pr_debug("PM: Entering %s sleep ", pm_states[state]);  
  26.     // 设备休眠  
  27.     error = suspend_devices_and_enter(state);  
  28.   
  29.  Finish:  
  30.     pr_debug("PM: Finishing wakeup. ");  
  31.     suspend_finish();  
  32.  Unlock:  
  33.     mutex_unlock(&pm_mutex);  
  34.     return error;  
  35. }  
  36.   
  37. int pm_suspend(suspend_state_t state)  
  38. {  
  39.     if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX)  
  40.         return enter_state(state);  
  41.     return -EINVAL;  
  42. }  
  43. EXPORT_SYMBOL(pm_suspend);  
在enter_state()中首先进入状态的判断,根据平台的特性判断是否支持此状态;然后再同步缓存;接着调用suspend_prepare()冻结大部分进程;然后再通过suspend_devices_and_enter()开始挂起设备。 2、冻结进程 [cpp] view plaincopy
  1. static int suspend_prepare(void)  
  2. {  
  3.     int error;  
  4.   
  5.     if (!suspend_ops || !suspend_ops->enter)  
  6.         return -EPERM;  
  7.   
  8.     pm_prepare_console();  
  9.   
  10.     // 通知进行休眠准备  
  11.     error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);  
  12.     if (error)  
  13.         goto Finish;  
  14.     // 禁止usermodehelper  
  15.     error = usermodehelper_disable();  
  16.     if (error)  
  17.         goto Finish;  
  18.     // 冻结所有可以冻结的进程  
  19.     error = suspend_freeze_processes();  
  20.     if (!error)  
  21.         return 0;  
  22.   
  23.     // 解冻所有进程  
  24.     suspend_thaw_processes();  
  25.     // 使能usermodehelper  
  26.     usermodehelper_enable();  
  27.  Finish:  
  28.     // 通知休眠结束  
  29.     pm_notifier_call_chain(PM_POST_SUSPEND);  
  30.     pm_restore_console();  
  31.     return error;  
  32. }  
这里有一个notifier机制后面要专门分析下。 3、挂起设备 [cpp] view plaincopy
  1. int suspend_devices_and_enter(suspend_state_t state)  
  2. {  
  3.     int error;  
  4.   
  5.     if (!suspend_ops)  
  6.         return -ENOSYS;  
  7.     // 处理器的休眠开始函数  
  8.     if (suspend_ops->begin) {  
  9.         error = suspend_ops->begin(state);  
  10.         if (error)  
  11.             goto Close;  
  12.     }  
  13.     // 休眠串口  
  14.     suspend_console();  
  15.     suspend_test_start();  
  16.     // 设备休眠  
  17.     error = dpm_suspend_start(PMSG_SUSPEND);  
  18.     if (error) {  
  19.         printk(KERN_ERR "PM: Some devices failed to suspend ");  
  20.         goto Recover_platform;  
  21.     }  
  22.     suspend_test_finish("suspend devices");  
  23.     if (suspend_test(TEST_DEVICES))  
  24.         goto Recover_platform;  
  25.     // 处理器休眠  
  26.     suspend_enter(state);  
  27.   
  28.  Resume_devices:  
  29.     suspend_test_start();  
  30.     // 设备唤醒  
  31.     dpm_resume_end(PMSG_RESUME);  
  32.     suspend_test_finish("resume devices");  
  33.     // 唤醒串口  
  34.     resume_console();  
  35.  Close:  
  36.     // 处理器的休眠结束函数  
  37.     if (suspend_ops->end)  
  38.         suspend_ops->end();