本文共 1744 字,大约阅读时间需要 5 分钟。
(转自:)
initval:创建eventfd时它所对应的64位计数器的初始值;
flags:eventfd文件描述符的标志,可由三种选项组成:EFD_CLOEXEC、EFD_NONBLOCK和EFD_SEMAPHORE。
EFD_CLOEXEC表示返回的eventfd文件描述符在fork后exec其他程序时会自动关闭这个文件描述符;
EFD_NONBLOCK设置返回的eventfd非阻塞;
EFD_SEMAPHORE表示将eventfd作为一个信号量来使用。
从上面描述中可以知道以下几点:
1.read函数会从eventfd对应的64位计数器中读取一个8字节的整型变量;
2.read函数设置的接收buf的大小不能低于8个字节,否则read函数会出错,errno为EINVAL;
3.read函数返回的值是按小端字节序的;
4.如果eventfd设置了EFD_SEMAPHORE,那么每次read就会返回1,并且让eventfd对应的计数器减一;如果eventfd没有设置EFD_SEMAPHORE,那么每次read就会直接返回计数器中的数值,read之后计数器就会置0。不管是哪一种,当计数器为0时,如果继续read,那么read就会阻塞(如果eventfd没有设置EFD_NONBLOCK)或者返回EAGAIN错误(如果eventfd设置了EFD_NONBLOCK)。
从上面描述中可以知道:
1.在没有设置EFD_SEMAPHORE的情况下,write函数会将发送buf中的数据写入到eventfd对应的计数器中,最大只能写入0xffffffffffffffff,否则返回EINVAL错误;
2.在设置了EFD_SEMAPHORE的情况下,write函数相当于是向计数器中进行“添加”,比如说计数器中的值原本是2,如果write了一个3,那么计数器中的值就变成了5。如果某一次write后,计数器中的值超过了0xfffffffffffffffe(64位最大值-1),那么write就会阻塞直到另一个进程/线程从eventfd中进行了read(如果write没有设置EFD_NONBLOCK),或者返回EAGAIN错误(如果write设置了EFD_NONBLOCK)。
除此之外,eventfd还支持select和poll,与一般的读写描述符相类似,这里就不多说了,如下所示:
现在写一个简单的例程,在父子进程中利用eventfd进行通信,如下所示:
#include#include #include #include #include #include using namespace std; int main(){ int evfd = eventfd(10,0); uint64_t wdata = 0; uint64_t rdata = 0; if(read(evfd,&rdata,8) == -1) { perror(NULL); if(errno!=EAGAIN)return 0; } cout<<"Init read : "< <
运行结果如下:
转载地址:http://zgmkb.baihongyu.com/