美文网首页
Android进程间通信-eventfd

Android进程间通信-eventfd

作者: 凯玲之恋 | 来源:发表于2021-01-20 00:27 被阅读0次

eventfd 是 Linux 2.6.22后才开始支持的一种IPC通信方式,它的作用主要时用来做事件通知,并且完全可以替代pipe,对于内核来说,eventfd的开销更低,eventfd只需要创建一个虚拟文件,而pipe需要创建两个,并且可用于select或epoll等多路复用模型中,来实现异步的信号通知功能。

所以eventfd 是很好用的一种IPC方式,而且它的使用也简单。

#include<sys/eventfd.h>  
#include <unistd.h>
int eventfd(unsigned int initval,int flags);//创建eventfd
ssize_t write(int fd, const void *buf, size_t count);   //写数据
ssize_t read(int fd, void *buf, size_t count);     //读数据

eventfd在内核里的核心是一个计数器counter,它是一个uint64_t的整形变量counter,初始值为initval。

当调用read() 函数读取eventfd时,会根据counter值执行下列操作:

  • 如果当前counter > 0,那么read返回counter值,并重置counter为0;
  • 如果当前counter等于0,那么read 函数阻塞直到counter大于0,如果设置了NONBLOCK,那么返回-1。

当调用write() 往eventfd写数据时,我们只能写入一个64bit的整数value

Eventfd在Android中的使用场景

正是因为eventfd比管道更简单高效,所以在Android6.0之后,Looper的唤醒就换成了eventfd。

Looper::Looper(bool allowNonCallbacks) :
        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
        mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
        mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
    mWakeEventFd = eventfd(0, EFD_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd.  errno=%d", errno);
​
    AutoMutex _l(mLock);
    rebuildEpollLocked();
}
​
void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ wake", this);
#endif
    uint64_t inc = 1;
    ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
    if (nWrite != sizeof(uint64_t)) {
        if (errno != EAGAIN) {
            ALOGW("Could not write wake signal, errno=%d", errno);
        }
    }
}

可以看到,Looper的构造函数中mWakeEventFd已经由之前提到的pipe换成了evnentfd,wake()函数也不是之前的写入一个“w”字符,而是写入了一个64位整数1。

相关文章

网友评论

      本文标题:Android进程间通信-eventfd

      本文链接:https://www.haomeiwen.com/subject/rnjhzktx.html