eventfd是从LINUX 2.6.27版本开始增加的,主要用于进程或者线程间的通信(如通知/等待机制的实现)。
实现了线程之间事件通知的方式,也可以用于用户态和内核通信。eventfd的缓冲区大小是sizeof(uint64_t);向其write可以递增这个计数器,read操作可以读取,并进行清零;eventfd也可以放到监听队列中,当计数器不是0时,有可读事件发生,可以进行读取。
函数原型:
#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);
第一个参数是计数器的初始值,通常设置为0。这个计数器(uint64_t)由linux内核用于维护事件对象。
第二个参数2.6.27版本才开始可以按位设置,在这之前只能设置0。可用参数如下:
lEFD_NONBLOCK
功能同open(2)的O_NONBLOCK,设置对象为非阻塞状态,如果没有设置这个状态的话,read(2)读eventfd,并且计数器的值为0 就一直堵塞在read调用当中,要是设置了这个标志,就会返回一个EAGAIN错误(errno = EAGAIN)。效果也如同额外调用select(2)达到的效果。
lEFD_CLOEXEC
这个标识被设置的话,调用exec后会自动关闭文件描述符,防止泄漏。
如果是2.6.26或之前版本的内核,flags 必须设置为0。
创建这个对象后,可以对其做如下操作:
1) write: 将缓冲区写入的8字节整形值加到内核计数器上。
2) read: 读取8字节值, 并把计数器重设为0. 如果调用read的时候计数器为0, 要是eventfd是阻塞的, read就一直阻塞在这里,否则就得到 一个EAGAIN错误。如果buffer的长度小于8那么read会失败, 错误代码被设置成 EINVAL。
3) poll select epoll
4) close: 当不需要eventfd的时候可以调用close关闭, 当这个对象的所有句柄都被关闭的时候,内核会释放资源。 为什么不是close就直接释放呢, 如果调用fork 创建进程的时候会复制这个句柄到新的进程,并继承所有的状态。
参考资料:
新的API signalfd、timerfd、eventfd使用说明 http://blog.jobbole.com/106933/ Linux
最高效的进(线)程间通信机制--eventfd blog.csdn.net/freeelinux/article/details/53511331
关于eventfd,epoll,线程间通信小记 https://www.cnblogs.com/burningTheStar/p/7064193.html