linux 消息队列 epoll,Handler 中的 epoll

在 Linux 中,epoll 机制是一个重要的机制。在 Android 中的 Handler,简单的利用了 epoll 机制,做到了消息队列的阻塞和唤醒。

epoll 机制相关的函数有

int epoll_create(int size);

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

因为对于Handler 对于 epoll 没有过于深入的使用,只是利用了 epoll 进行了阻塞和唤醒,还是比较好理解的。

void Looper::rebuildEpollLocked( ){

mEpollFd = epoll_create(EPOLL_SIZE_HINT);

struct epoll_event eventItem;

memset(&eventItem, 0, sizeof(epoll_event));

//触发该事件,表示对应的文件描述符上有可读数据,后面也是在 write 一个字符,使得可以唤醒

eventItem.events = EPOLLIN;

eventItem.data.fd = mWakeEventFd;

int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, &eventItem);

...

}

于是,便利用 epoll 机制在mEpollFd上添加(EPOLL_CTL_ADD)了监听的 fd(mWakeEventFd);

在 java 层,next( )@Message 会阻塞到nativePollOnce(long ptr, int timeoutMillis),特别的是,当没有消息时,timeoutMillis = -1表示一直阻塞。如果有 delay 的消息,则 timeoutMillis 表示 delay的时间。

int Looper::poolInner(int timeoutMillis){

...

int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

...

}

此时利用epoll 机制在 epoll_wait()上设置超时时间。当 timeoutMillis = -1时会一直等待知道有新消息来。否则当超时时间到达时,会返回到 next()@Message就可以处理那条 delay 的消息了。

当有新消息来临时并且是立刻执行的,enqueueMessage()@Message 会调用nativeWake(),否则会根据新来的消息的 delay 时间和队列中的 delay 时间进行对比,消息队列是按照msg 的到达时间和 delay 时间进行排序,如果新来的消息在前并且需要 delay 也会进行 wake()

void Looer::wake( ){

uint64_t inc = 1;

ssize_t nWrite = TEMP_FAIURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_4)));

}

当往 mWakeEventFd 写入一个 1,便会从 epoll_wait() 马上返回。进行新一轮的消息处理。

另外,native 层的 Looper 的 epoll 机制没有这么简单,只是在 Handler 中只是简单地使用了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值