【问题标题】:What does epoll do with a file descriptor that refers to a directory?epoll 对引用目录的文件描述符做了什么?
【发布时间】:2012-08-06 17:36:39
【问题描述】:

正如标题所说,如果我用epoll注册了一个文件描述符,它是一个目录,它是做什么的?

【问题讨论】:

  • 如果要在 Linux 上监控文件系统事件,请使用inotify

标签: linux file-descriptor epoll


【解决方案1】:

Nothing -- 注册 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

为了弄清楚这里发生了什么,我去了源头。我happen to know 认为epoll 的大部分行为是由目标文件对应的struct file_operations 上的-&gt;poll 函数决定的,这取决于所讨论的文件系统。我选择ext4作为典型例子,看了fs/ext4/dir.c,其中definesext4_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。因此,回到在fs/eventpoll.c 中定义的epoll,我们查找poll 是否为NULL 的检查,并在epoll_ctl 系统调用定义中找到early on

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

正如我们的测试所表明的,如果目标文件不支持poll,插入尝试将失败并返回EPERM

其他文件系统可能会在其目录文件对象上定义.poll 方法,但我怀疑很多人这样做。

【讨论】:

  • dirfd(opendir("/tmp")) 是否优于 open(path, O_RDONLY|O_DIRECTORY);?只是风格问题。使用opendir 不会神奇地使 fs 支持投票。
  • dirfd(opendir("...")) 更便携,因此通常可能是首选。我是一名 Linux 内核黑客,所以我个人倾向于默认使用系统调用接口,即使它不是最合适的,因为我更了解它。显然在这里它并不重要,因为epoll 也是 Linux 特定的。
猜你喜欢
  • 1970-01-01
  • 2011-06-18
  • 1970-01-01
  • 2016-10-19
  • 2014-12-20
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
相关资源
最近更新 更多