epoll是如何处理引用目录的文件描述符的?

就像标题所说的那样,我注册了一个文件描述符,这个文件描述符是一个带有epoll的目录,它有什么作用?

什么都没有 – 调用注册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大部分行为是由目标文件对应的struct file_operations上的->poll函数确定的,这取决于所讨论的文件系统。 我选择了ext4作为一个典型的例子,并且查看了定义 ext4_dir_operations fs/ext4/dir.c ,如下所示:

 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 。 所以,回到fs/eventpoll.c定义的epoll,我们查找poll为NULL的检查,我们在epoll_ctl syscall定义的早期找到一个:

 /* The target file descriptor must support poll */ error = -EPERM; if (!tfile->f_op || !tfile->f_op->poll) goto error_tgt_fput; 

正如我们的测试所指出的那样,如果目标文件不支持poll ,插入尝试将仅仅通过EPERM失败。

其他文件系统有可能在他们的目录文件对象上定义.poll方法,但我怀疑很多。