eventfd 函数使用介绍
从Linux 2.6.27版本开始,新增了不少系统调用,其中包括eventfd,它的主要是用于进程或者线程间的通信(如通知/等待机制的实现)。函数原型: #include/** function: 创建eventfd* @initval: 信号量的初始值* @flags: (2.6.27以上内核有效)可以设置一下标志位,如果是2.6.26或之前版
·
从Linux 2.6.27版本开始,新增了不少系统调用,其中包括eventfd,它的主要是用于进程或者线程间的通信(如通知/等待机制的实现)。
函数原型:
#include <sys/eventfd.h>
/*
* function: 创建eventfd
* @initval: 信号量的初始值
* @flags: (2.6.27以上内核有效)可以设置一下标志位,如果是2.6.26或之前版本的内核,flags 必须设置为0。
* EFD_NONBLOCK 是否阻塞
* EFD_CLOEXEC close-on-exec标记,当exec时是否关闭该文件
* return value:文件描述符fd
int eventfd(unsigned int initval, int flags);
eventfd在内核里的核心是一个计数器counter,它是一个uint64_t的整形变量counter,初始值为initval。
1.read(eventfd_read)
消费者需要对信号量进行down操作时,调用read从eventfd读即可。read返回值:
如果当前counter > 0,那么read返回counter值,并重置counter为0;
- 如果当前counter等于0,那么read 1)阻塞直到counter大于0;2)如果设置了NONBLOCK,那么返回-1,并设置errno为EAGAIN。
可以看到,eventfd实现的资源是一次性消耗品,只允许一次read。
2.write(eventfd_write)
生产者需要执行up操作时,调用write写一个64bit的整数value到eventfd即可。write返回值:
- counter最大能存储的值是 0xffff ffff ffff fffe(以max表示此值),那么write尝试将value加到counter上,如果结果超过max,那么write一直阻塞直到有read操作发生,或者返回-1并设置errno为EAGAIN。
所以write可以多次连续调用,但read读一次即可清零。实质上它应该是一个二元信号量,只有0和非0两种状态。但是应用程序也可以利用counter的值实现自己的逻辑,比如每次write都加1,那么read就能够知道在两次调用之间有多少次write操作发生,也就表示对应的事件发生了多少次。
例子:
#include <sys/eventfd.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int fd;
uint64_t buffer;
void threadFunc(void) //线程函数
{
int t;
while(1)
{
t = read(fd,&buffer,sizeof(buffer)); //阻塞等待fd可读,及通知事件发生
if(sizeof(buffer) < 8)
{
printf("buffer错误\n");
}
printf("t = %llu buffer = %llu\n",t,buffer);
if(t == 8)
{
printf("唤醒成功\n");
}
}
}
int main(void)
{
uint64_t buf = 1;
int ret;
pthread_t tid;
if((fd = eventfd(0,0)) == -1) //创建事件驱动的文件描述符
{
printf("创建失败\n");
}
//创建线程
if(pthread_create(&tid,NULL,threadFunc,NULL) < 0)
{
printf("线程创建失败\n");
}
while(1)
{
ret = write(fd,&buf,sizeof(buf)); //通过往fd里写东西来进行事件通知
if(ret != 8)
{
printf("写错误\n");
}
sleep(2); //没2s通知一次
}
return 0;
}
更多推荐
已为社区贡献1条内容
所有评论(0)