Android待机的suspend_sys_sync_queue分析


Android的4.0在待机机制上和之前版本大同小异,也可以说是机制相对完善并没多大的问题反馈出来。不过有个细节的地方,改动幅度较大,来看看


在linux待机机制中,开始待机的时候会调用sys_sync函数,sys_sync系统调用被用户空间函数调用,

用来将缓存中的数据写入块设备,sys_sync系统调用将buffer、inode和super在缓存中的数据写入设备。

此函数的介绍参看博文链接http://blog.chinaunix.net/uid-24237502-id-106067.html。


sys_sync函数执行时间长度依文件系统而定,长至上百毫秒,也有若干毫秒。函数执行的必要性如何呢?

如果有种需求,在很短时间(毫秒级)内需要连续进出待机,sys_sync函数是否需要每次都执行一遍呢?

如果只第一次执行,会有什么隐患问题呢?


由于待机请求有自动超时待机和按键进入待机,自动进入待机问题不大,基本上是闹钟或者计时时间发起事件,

而按键进入待机不同,按键时间贯穿kernel到android上层,涉及节点处理,文件系统操作,

所以对同步设备节点数据sys_sync就有需求,可以看出来,android4.0在对sys_sync的调用修改上,也是考虑到按键进入待机的隐藏问题。

那到底做了哪些修改呢?


suspend_sys_sync_queue有三个地方在调用

Earlysuspend.c (kernel\power)

Suspend.c (kernel\power):

Wakelock.c (kernel\power):

定义是在Wakelock.c (kernel\power)中

这个函数实现执行队列中suspend_sys_sync_work

void suspend_sys_sync_queue(void){int ret;spin_lock(&suspend_sys_sync_lock);ret = queue_work(suspend_sys_sync_work_queue, &suspend_sys_sync_work);if (ret)suspend_sys_sync_count++;spin_unlock(&suspend_sys_sync_lock);}

suspend_sys_sync_work_queue =create_singlethread_workqueue("suspend_sys_sync");

static void suspend_sys_sync(struct work_struct *work){if (debug_mask & DEBUG_SUSPEND)pr_info("PM: Syncing filesystems...\n");sys_sync();if (debug_mask & DEBUG_SUSPEND)pr_info("sync done.\n");spin_lock(&suspend_sys_sync_lock);suspend_sys_sync_count--;spin_unlock(&suspend_sys_sync_lock);}static DECLARE_WORK(suspend_sys_sync_work, suspend_sys_sync);

所以调用 suspend_sys_sync_queue,其实最后还是调用sys_sync,只是增加对sys_sync执行次数的计数,以及队列方式执行并非立即执行。

队列方式执行,是对执行的时间上有要求,那么它到底需要等待多少时间呢?相对什么等待呢?

待机,对系统而言,就是冻结,退出待机时候,对系统而言相当于什么事情都没发生。

标准linux待机在待机的开始阶段,就会冻结所有的进程和任务,在唤醒时候恢复它们。

由于进程在kernel空间处理的复杂度,linux在冻结进程和任务的时候,不支持进程还跑在kernel空间,否则就是abort处理。

问题就出来了,最后一次按键进入待机,按键时间从键值采集、键值上报、上层对上报值的轮询、对按键事件分发、对按键时间的处理等,

都需要一定时间,如果在进程未能较快回到用户空间,freeze_processes的时候,如下

printk("Freezing user space processes ... ");error = try_to_freeze_tasks(true);if (error)goto Exit;printk("done.\n");

在freezing user space processes会abort。

补充一下说明:这里针对的不全是最后一次按键,我们知道android为了增加用户体验,在超时进入待机时候,会启动一个5秒的定时闹钟,

从而阻止5秒内真正进入待机,在用户体验上,就是屏幕暗下来的5秒内,只要用户及时点亮屏幕,系统就没真正待机,不会有锁屏界面。

开发员在此过程中会看到freezing user space processes abort,是因为系统启动了alarm,从而推出待机,系统恢复。

这里增加了一个timer,用于等待sys_sync执行完毕

error = suspend_sys_sync_wait();if (error)goto Exit;

int suspend_sys_sync_wait(void){suspend_sys_sync_abort = false;if (suspend_sys_sync_count != 0) {mod_timer(&suspend_sys_sync_timer, jiffies +SUSPEND_SYS_SYNC_TIMEOUT);wait_for_completion(&suspend_sys_sync_comp);}if (suspend_sys_sync_abort) {pr_info("suspend aborted....while waiting for sys_sync\n");return -EAGAIN;}return 0;}

static bool suspend_sys_sync_abort;static void suspend_sys_sync_handler(unsigned long);static DEFINE_TIMER(suspend_sys_sync_timer, suspend_sys_sync_handler, 0, 0);/* value should be less then half of input event wake lock timeout value * which is currently set to 5*HZ (see drivers/input/evdev.c) */#define SUSPEND_SYS_SYNC_TIMEOUT (HZ/4)static void suspend_sys_sync_handler(unsigned long arg){if (suspend_sys_sync_count == 0) {complete(&suspend_sys_sync_comp);} else if (has_wake_lock(WAKE_LOCK_SUSPEND)) {suspend_sys_sync_abort = true;complete(&suspend_sys_sync_comp);} else {mod_timer(&suspend_sys_sync_timer, jiffies +SUSPEND_SYS_SYNC_TIMEOUT);}}

等待的时间should be less then half of input event wake lock timeout value,

evdev事件会超时50ms,这里的timeout需要小于25ms,此处设置为2.5ms。

对timeout的要求,应该是为了能够更快地在evdev超时后执行timer的handler。


以上这些代码,都可以追踪CONFIG_SUSPEND_SYNC_WORKQUEUE宏定义。






更多相关文章

  1. android 4.04的应用程序启动过程及与Zygote的交互(基于静态源码分
  2. Android(安卓)照相机
  3. Android(安卓)四大组件 简介
  4. Android中native进程内存泄露的调试技巧
  5. Android(安卓)Wear手表蓝牙连接Android(安卓)Studio调试/开发的
  6. Android(安卓)JNI
  7. Android(安卓)Power Management
  8. Android(安卓)AsyncTask实现异步任务的执行
  9. Android(安卓)实现QQ第三方登录

随机推荐

  1. android TextView xml中设置最大行数
  2. android 问题总结
  3. android 开发包的离线安装方式
  4. Android —— 第一次安装 Android Studio
  5. Android 四大组件之Activity生命周期
  6. Android Studio apk生成路径
  7. android 语言切换过程分析
  8. 1.4 android——UI之 UI界面属性用法与注
  9. android 网络开发
  10. Android(安卓)sqlite cursor的遍历