epoll 机制相关的函数有
因为对于Handler 对于 epoll 没有过于深入的使用,只是利用了 epoll 进行了阻塞和唤醒,还是比较好理解的。
于是,便利用 epoll 机制在mEpollFd上添加(EPOLL_CTL_ADD)了监听的 fd(mWakeEventFd)
在 java 层,next( )@Message 会阻塞到nativePollOnce(long ptr, int timeoutMillis),特别的是,当没有消息时,timeoutMillis = -1表示一直阻塞。如果有 delay 的消息,则 timeoutMillis 表示 delay的时间。
此时利用epoll 机制在 epoll_wait()上设置超时时间。当 timeoutMillis = -1时会一直等待知道有新消息来。否则当超时时间到达时,会返回到 next()@Message就可以处理那条 delay 的消息了。
当有新消息来临时并且是立刻执行的,enqueueMessage()@Message 会调用nativeWake(),否则会根据新来的消息的 delay 时间和队列中的 delay 时间进行对比,消息队列是按照msg 的到达时间和 delay 时间进行排序,如果新来的消息在前并且需要 delay 也会进行 wake()
当往 mWakeEventFd 写入一个 1,便会从 epoll_wait() 马上返回。进行新一轮的消息处理。
另外,native 层的 Looper 的 epoll 机制没有这么简单,只是在 Handler 中只是简单地使用了。
Linux中的epoll
这个bug并没有真正的解决。:可以参考netty的解决办法。对selector的select操作周期进行统计,如果在某个周期
内连续发生了N次空轮询,则说明很可能发生了epoll死循环的bug了