eventfd是linux 2.6.22后系统提供的一个轻量级的进程间通讯的系统调用,eventfd经过一个进程间共享的64位计数器完成进程间通讯,这个计数器由在linux内核空间维护,用户能够经过调用write方法向内核空间写入一个64位的值,也能够调用read方法读取这个值。linux
#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);
复制代码
建立的时候能够传入一个计数器的初始值initval。 第二个参数flags在linux 2.6.26以前的版本是没有使用的,必须初始化为0,在2.6.27以后的版本flag才被使用。ios
EFD_CLOEXEC(2.6.27~):c++
A copy of the file descriptor created by eventfd() is inherited by the child produced by fork(2). The duplicate file descriptor is associated with the same eventfd object. File descriptors created by eventfd() are preserved across execve(2), unless the close-on-exec flag has been set.bash
eventfd()会返回一个文件描述符,若是该进程被fork的时候,这个文件描述符也会复制过去,这时候就会有多个的文件描述符指向同一个eventfd对象,若是设置了EFD_CLOEXEC标志,在子进程执行exec的时候,会清除掉父进程的文件描述符less
EFD_NONBLOCK(2.6.27~): 就如它字面上的意思,若是没有设置了这个标志位,那read操做将会阻塞直到计数器中有值。若是没有设置这个标志位,计数器没有值的时候也会当即返回-1;ui
EFD_SEMAPHORE(2.6.30~): 这个标志位会影响read操做,具体能够看read方法中的解释spa
read: 读取计数器中的值code
write: 向计数器中写入值对象
close: 关闭文件描述符进程
#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
int main() {
int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
eventfd_write(efd, 2);
eventfd_t count;
eventfd_read(efd, &count);
std::cout << count << std::endl;
close(efd);
}
复制代码
上面的程序中咱们建立了一个eventfd,并将它的文件描述符保存在efd中,而后调用eventfd_write向计数器中写入数字2,而后调用eventfd_read读取计数器中的值并打印处理,最后关闭eventfd。 运行结果:
count=2
复制代码
#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
int main() {
int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
eventfd_write(efd, 2);
eventfd_write(efd, 3);
eventfd_write(efd, 4);
eventfd_t count;
int read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
close(efd);
}
复制代码
运行结果:
read_result=0
count=9
read_result=-1
count=9
复制代码
从运行结果咱们能够看出当屡次调用eventfd_write的时候,计数器一直在累加,可是eventfd_read只需调用一次就能够将计数器中的数取出来,若是再次调用eventfd_read将会返回失败。
#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
int main() {
int efd = eventfd(0, EFD_CLOEXEC);
eventfd_write(efd, 2);
eventfd_write(efd, 3);
eventfd_write(efd, 4);
eventfd_t count;
int read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
close(efd);
}
复制代码
运行结果:
read_result=0
count=9
复制代码
和前一个运行结果直接返回-1相比,若是去掉EFD_NONBLOCK标志位,程序会在计数器没有值的状况下一直阻塞在eventfd_read方法。
#include <sys/eventfd.h>
#include <unistd.h>
#include <iostream>
int main() {
int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC | EFD_SEMAPHORE);
eventfd_write(efd, 2);
eventfd_t count;
int read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
read_result = eventfd_read(efd, &count);
std::cout << "read_result=" << read_result << std::endl;
std::cout << "count=" << count << std::endl;
close(efd);
}
复制代码
运行结果:
read_result=0
count=1
read_result=0
count=1
read_result=-1
count=1
复制代码
能够看到设置了EFD_SEMAPHORE后,每次读取到的值都是1,且read后计数器也递减1。