当前位置: 首页 > 科技观察

epoll可以监控普通文件吗?

时间:2023-03-12 06:06:58 科技观察

本文转载自微信公众号《Linux内核那些事儿》,作者songsong001。转载本文请联系Linux内核那些事儿公众号。epoll是Linux系统中常用的多路复用I/O组件,一般用于监控socket是否可以进行I/O操作。那么,epoll可以监听普通文件吗?我们通过下面的例子来验证epoll是否可以监听普通文件:#include#include#includeintmain(){intepfd,fd;structepoll_eventev,events[2];intresult;epfd=epoll_create(10);if(epfd<0){perror("epoll_create()");return-1;}fd=open("./test.txt",O_RDONLY|O_CREAT);if(fd<0){perror("open()");return-1;}ev.events=EPOLLIN;result=epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev);if(result<0){perror("epoll_ctl()");return-1;}epoll_wait(epfd,events,2,-1);return0;}编译运行,结果如下:[vagrant@localhostepoll]$gccepoll.c-oepoll[vagrant@localhostepoll]$./epollepoll_ctl():Operationnotpermitted可以看到上面的运行结果报错Operationnotpermitted,也就是说epoll不能监控普通文件,为什么呢?追根究底还是要有求真热心的,所以一定要搞清楚为什么epoll不能监听普通文件。因为在上面的例子中,epoll_ctl函数报错,我们首先要从epoll_ctl的源码说起,如下:SYSCALL_DEFINE4(epoll_ctl,int,epfd,int,op,int,fd,structepoll_event__user*,event){互错;structfile*file,*tfile;...error=-EBADF;file=fget(epfd);//epoll句柄对应的文件对象if(!file)gotoerror_return;tfile=fget(fd);//监听的file句柄对应的文件对象if(!tfile)gotoerror_fput;error=-EPERM;//Operationnotpermitted错误号if(!tfile->f_op||!tfile->f_op->poll)gotoerror_tgt_fput;...error_tgt_fput:fput(tfile);error_fput:fput(file);error_return:returnerror;}从上面的代码可以看出,当被监控的文件没有提供poll接口时,会返回一个EPERM错误,也就是错误号不允许操作。所以Operationnotpermitted的原因是被监控的文件没有提供poll接口。由于我们的文件系统是ext4,我们看看ext4文件系统中的文件是否提供了poll接口(位于文件/fs/ext4/file.c):write=do_sync_write,.aio_read=generic_file_aio_read,.aio_write=ext4_file_write,.unlocked_ioctl=ext4_ioctl,.mmap=ext4_file_mmap,.open=ext4_file_open,.release=ext4_release_file,.fsync=ext4_sync_file,.splice_read=generic_file_splice_read,.splice_writes;ext4文件的文件操作函数集设置为ext4_file_operations(即:file->f_op=ext4_file_operations),从上面代码可以看出,ext4_file_operations没有提供poll接口。所以调用epoll_ctl将文件添加到epoll进行监控时,会返回Operationnotpermitted的错误。从上面的分析我们可以看出,当文件系统提供poll接口时,可以将文件添加到epoll中进行监控。