IP地址检测
视频播放器
输入关键词搜索
登录
Android是如何利用epoll实现handler机制的?

Android是如何利用epoll实现handler机制的?

2023-03-24
编程开发

事件循环

javascript中的event loop是单线程模型,和android的Looper机制一样,底层实现用的epoll机制。即一个进程只有一条主线程用来更新UI,因此主线程不能做耗时操作,否则界面会卡死。

现在看来好像带界面的都用的是单线程模型,至少android和浏览器中的javascript v8引擎是这样的

epoll

再说一下epoll的事情。Android里面是利用了epoll的wait方法,epoll wait方法可以传0,传-1,或者传一个具体的值。

  • 0 代表wait函数立即返回,
  • -1 代表wait一直监听(这个行为不会抢占cpu资源)直到监听事件(文件可写,文件可读...)的发生,
  • 一个具体的值 代表timeout,即在指定时间内返回。

流程

处理Message

首先Android会创建一个Looper对象,调用loop方法,方法里面有一个for死循环,调用MessageQueue的next()方法获取消息。巧妙的地方是,MessageQueue并没有直接返回一个Message,而是用了一套障眼法。MessageQueue中的next()方法也是一个死循环。

内部代码是这样执行的:

第一次循环调用epoll的wait方法,时间参数传0,代表立刻返回,(这里有点试探性的意思,主要就是判断当前messagequeue有没有东西可以拿,没有message拿,就直接wait(-1)死等;有message拿,就看能不能处理),

  1. message列表为空,代表没有message消息需要处理,调用wait(-1)一直等待,直到新的消息出现。
  2. message有内容,android会取出排在列表头的第一个message,比较message的when参数和当前时间uptimeMillis,如果时间到了可以执行,把message从queue中取出,然后执行这个消息的dispatchMessage方法,接着继续调用wait(0);如果时间没到不可以执行,就判断还需要等待多少秒才可以执行,也就是when参数减去uptime参数,那么得出的结果就是还需要等待的时间,聪明的android作者直接将这个值传入到epoll的wait方法中,调用wait(还需要等待的时间),等到timeout结束,android就可以取出message,并执行相应的操作。Android将epoll的等待机制和MessageQueue进行了巧妙的组合,实在高明

通过上面的流程,android利用wait方法间接实现了消息的获取,和cpu的资源释放。简单点说就是,有消息就处理,没有消息就等待

如遇到同步屏障消息(即msg.target为null时),只执行异步消息(即msg.isAsynchronous()为true)

post Message

post消息很简单,post的时候,会把每个消息的绝对时间(uptimeMillis)记录下来,插入消息队列时,根据uptimeMillis进行排序。如果新的message插入到队头,就要激活这个消息队列,目的是让Looper方法更新wait的参数(-1,0,具体的值)。据了解,Android作者好像写入了一个w字母,记不太清了,其他没有特别的地方了

总结:从整体上看,android并没有充分利用epoll的所有特点,仅仅是使用了wait方法。顶多就是写入一个w激活一下。发消息和处理消息是解耦的

postMessage发送的消息都是同步消息,即msg.isAsynchronous()为false

⭐️同步屏障

public int postSyncBarrier() {
    return postSyncBarrier(SystemClock.uptimeMillis());
}

private int postSyncBarrier(long when) {
    // Enqueue a new sync barrier token.
    // We don't need to wake the queue because the purpose of a barrier is to stall it.
    synchronized (this) {
        final int token = mNextBarrierToken++;
        msg.markInUse();
        msg.when = when;
        msg.arg1 = token;

        Message prev = null;
        Message p = mMessages;
        if (when != 0) {
            while (p != null && p.when <= when) {
                prev = p;
                p = p.next;
            }
        }
        if (prev != null) { // invariant: p == prev.next
            msg.next = p;
            prev.next = msg;
        } else {
            msg.next = p;
            mMessages = msg;
        }
        return token;
    }
}

把同步屏障消息添加到MessageQueue中,按when时间排序。同步屏障消息与普通的消息区别是,target为null。

说了这么多,Sync Barrier就是安卓 内部用以实现优先级队列的一种方式。

当队列中出现Sync barrier(具体实现上就是Message#target为null)时,就会忽略所有同步消息,寻找异步消息(isAsynchrouns为true)的消息,然后优先处理它。

需要注意的是,把消息标记为异步,以及向消息队列中发送Sync barrier,这些API全部都是hide的,也就是说app中是无法使用的,通过反射也许能调用成功,但风险也较大,后续会被谷歌限制调用。换言之,这东西只能在Frameworks层内部自己使用。

THE END
0/500
暂无评论
📢网站公告
欢迎来到这里
⚙️实用工具
html转pdfmarkdown编辑器
本站推荐:腾讯云服务器仅需2.3折 (点击直达)
用户协议
隐私政策
Build Time: 2025-04-26 11:07:00