Looper中的睡眠等待与唤醒机制

C++Looper中的睡眠和唤醒机制是通过pollOncewake函数提供的,它们又是利用操作系统(Linux内核)的epoll机制来完成的。当被监控的文件(通过epoll_ctlEPOLL_CTL_ADD添加进去)可I/O时,epoll_wait调用会从睡眠中醒来,这时,可以检查是哪个(或哪些)文件描述符对应的文件可以进行I/O读写了,从而做出进一步处理。使用者利用它们就可以拥有睡眠等待和唤醒机制。下面详述。

Looper的构造函数中,会创建一个管道(下面的行73),然后调用epoll_create获取一个epoll的实例的描述符(行88),最后将管道读端描述符作为一个事件报告项添加给epoll(行95)。这样,当管道读端有数据可读时,将会得到报告。Looper的构造函数如下(见文件Looper.cpp:


LooperpollOnce函数将最终调用到其pollInner函数。在后者里面,将调用epoll_wait睡眠等待其监控的文件描述符是否有可I/O事件的到来,若有(哪怕只有一个),epoll_wait将会醒来,然后可检查是哪个文件描述符上的可I/O事件。pollInner函数中的相关代码如下(见文件Looper.cpp:



可见,在线程循环中调用了LooperpollOnce函数,将导致睡眠等待在上面的行218处的epoll_wait上。当向消息队列发送消息并进行唤醒时,行218将被唤醒,因此从pollOnce函数中返回,可以从消息队列中取出消息进行处理。

Looperwake函数用于向管道中写入字符(下面的行367),以唤醒pollOnce


下面来看一下Java层的MessageQueue如何利用这种机制。

前面提到在android.os.MessageQueuenext函数中取出下一个消息时,会调用到native层实现的函数nativePollOnce时,实际调用到了如下native实现(见文件android_os_MessageQueue.cpp):


上面行157pollOnce函数代码是(见文件android_os_MessageQueue.cpp):


这样,它们就通过LooperpollOnce实现了在Looper中的管道上的读端上的睡眠等待。

android.os.MessageQueueenqueueMessage函数往队列上添加了一个新消息或removeSyncBarrier移除了同步屏障后,可能需要调用nativeWake唤醒,其native实现为:(见文件android_os_MessageQueue.cpp):


上面的行162调用的又是下面的函数,代码如下(见文件android_os_MessageQueue.cpp):


这样,Looper将向管道写端写入字符,唤醒其在管道读端上的睡眠等待。

因此,通过借助于LooperwakepollOnce函数,可以让别的消息队列(如Java层的消息队列)拥有睡眠唤醒机制:没有消息时pollOnce调用者将睡眠等待,有消息时让wake函数去唤醒睡眠等待。


本文节选自《深入剖析Android系统》一书

杨长刚

电子工业出版社出版

更多相关文章

  1. Android程式编写及调试新手入门-3
  2. 星云精准测试对安卓底层驱动代码的测试案例分析
  3. Android音频系统之AudioTrack起播线与underrun问题研究(Android(
  4. Android(安卓)Rild模块源码分析
  5. android在framework层增加自己的service仿照GPS
  6. 可左右两侧挤压傍边布局的Android抽屉
  7. Dalvik虚拟机JNI方法的注册过程分析
  8. Android单元测试研究与实践
  9. 如何用Android(安卓)webview播放HTML5 video标签

随机推荐

  1. android:20.活用Android的Message Queue(
  2. Android中shape的使用
  3. 菜鸟级的android程序员面试时候需要掌握
  4. Android四大视图动画图文详解
  5. Android性能调优工具TraceView介绍
  6. Android ListView 去除底色、选中色、阴
  7. Android夸进程通信机制一:多进程简介
  8. android 2048游戏、kotlin应用、跑马灯、
  9. Android中layout_gravity和gravity的区别
  10. 七款android地图 [Map] 开源项目框架分类