就像标题说的那样,如果我用epoll注册了一个文件描述符,它是一个目录,它是做什么的?
问问题
3830 次
1 回答
17
什么都没有——注册 fd 的调用(至少对于常见的 Linux 文件系统)将失败,并显示EPERM
.
我使用以下演示程序对此进行了测试:
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(void) {
int ep = epoll_create1(0);
int fd = open("/tmp", O_RDONLY|O_DIRECTORY);
struct epoll_event evt = {
.events = EPOLLIN
};
if (ep < 0 || fd < 0) {
printf("Error opening fds.\n");
return -1;
}
if (epoll_ctl(ep, EPOLL_CTL_ADD, fd, &evt) < 0) {
perror("epoll_ctl");
return -1;
}
return 0;
}
结果如下:
[nelhage@hectique:/tmp]$ make epoll
cc epoll.c -o epoll
[nelhage@hectique:/tmp]$ ./epoll
epoll_ctl: Operation not permitted
为了弄清楚这里发生了什么,我去了源头。我碰巧知道大多数行为epoll
是由目标文件对应的->poll
函数决定的,这取决于所讨论的文件系统。struct file_operations
我选择ext4
了一个典型的例子,并查看了fs/ext4/dir.c
,它的定义 ext4_dir_operations
如下:
const struct file_operations ext4_dir_operations = {
.llseek = ext4_dir_llseek,
.read = generic_read_dir,
.readdir = ext4_readdir,
.unlocked_ioctl = ext4_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext4_compat_ioctl,
#endif
.fsync = ext4_sync_file,
.release = ext4_release_dir,
};
请注意缺少.poll
定义,这意味着它将被初始化为NULL
. 因此,回到定义在 中的 epoll,fs/eventpoll.c
我们寻找是否为poll
NULL 的检查,并且我们在系统调用定义的早期找到了一个:epoll_ctl
/* The target file descriptor must support poll */
error = -EPERM;
if (!tfile->f_op || !tfile->f_op->poll)
goto error_tgt_fput;
正如我们的测试所表明的,如果目标文件不支持poll
,则插入尝试将失败,并显示EPERM
.
其他文件系统可能会在其目录文件对象上定义.poll
方法,但我怀疑很多人会这样做。
于 2012-08-06T18:04:55.330 回答