来源
Linux专有的同步机制, 需要内核高于2.6.22, 下面是引用 <<The Linux Programming Interface>>这本书中的说明:
从man手册中有如下的描述:
eventfd() creates an "eventfd object" that can be used as an event wait/notify mechanism by user-space applications, and by the kernel to notify user-space applications of events. The object contains
an unsigned 64-bit integer (uint64_t) counter that is maintained by the kernel. This counter is initialized with the value specified in the argument initval.
特征
在内核创建eventfd object, 有一个an unsigned 64-bit integer (uint64_t) counter, 这个值由内核管理
正如eventfd中包含的fd, 可以知道eventfd创建的这个eventfd对象和file open类似,然后接下来的操作都是由这个fd来指定, 而在linux下面fd的意义对于不同的进程是不一样的,因此eventfd仅仅适用于进程内(Parent child Process)的通讯, 而Android里面借助binder是可以跨进程传递fd.
适用范围
适用于Processes(父子)之间通讯,用于 an event wait/notify mechanism模型, 和文件使用write/read类似,当没有设置O_NONBLOCK flag的时候:
- 当文件有数据的时候 <--> eventfd中的Int不为0 <--> 会马上返回
- 当文件有数据的时候 <--> eventfd中的Int==0 <--> block等待值不为0/等待buffer不为空
- Wait: Read --> Object关联的INT值为0 --> Blocking
- Notify: Write nonzero给关联INT--> Notify --> Read return
而这个Wait/Notify模型,一般用于控制程序的执行顺序,与Semaphore模型类似, 因此, eventfd的打开flag中有一个EFD_SEMAPHORE选项
如果期望不要block可以使用fcntl来更改,例如下面函数来源于BlueDroid中(semophore.c):
bool semaphore_try_wait(semaphore_t *semaphore) {
assert(semaphore != NULL);
assert(semaphore->fd != INVALID_FD);
int flags = fcntl(semaphore->fd, F_GETFL);
if (flags == -1) {
LOG_ERROR("%s unable to get flags for semaphore fd: %s", __func__, strerror(errno));
return false;
}
if (fcntl(semaphore->fd, F_SETFL, flags | O_NONBLOCK) == -1) {
LOG_ERROR("%s unable to set O_NONBLOCK for semaphore fd: %s", __func__, strerror(errno));
return false;
}
eventfd_t value;
if (eventfd_read(semaphore->fd, &value) == -1)
return false;
if (fcntl(semaphore->fd, F_SETFL, flags) == -1)
LOG_ERROR("%s unable to resetore flags for semaphore fd: %s", __func__, strerror(errno));
return true;
}
使用方法
可以使用glibc的wrap函数来使用:
The GNU C library defines an additional type, and two functions that attempt to abstract some of the details of reading and writing on an eventfd file descriptor:
typedef uint64_t eventfd_t;
int eventfd_read(int fd, eventfd_t *value);
int eventfd_write(int fd, eventfd_t value);
参考
http://www.sourcexr.com/articles/2013/10/26/lightweight-inter-process-signaling-with-eventfd
Linux Programming Interface的作者对IPC的Presentation视频
http://zorksylar.github.io/epoll-eventfd.html