Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux epoll如何处理引用目录的文件描述符?_Linux_File Descriptor_Epoll - Fatal编程技术网

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

Linux epoll如何处理引用目录的文件描述符?,linux,file-descriptor,epoll,Linux,File Descriptor,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)

正如标题所说,如果我用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;
}
为了弄清楚这里发生了什么,我去了源头。我认为,
epoll
的大多数行为是由目标文件对应的
struct file_操作上的
->poll
函数决定的,这取决于所讨论的文件系统。我选择了
ext4
作为一个典型的例子,并研究了
fs/ext4/dir.c
,其
ext4\u dir\u操作
,如下所示:

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\u ctl
系统调用定义中找到一个:

/* The target file descriptor must support poll */
error = -EPERM;
if (!tfile->f_op || !tfile->f_op->poll)
    goto error_tgt_fput;
正如我们的测试所示,如果目标文件不支持
轮询
,则插入尝试将失败,返回
EPERM


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

如果您想在Linux上监视文件系统事件,请使用.Is
dirfd(opendir(“/tmp”)
优于
open(path,O|RDONLY | O| O|directory)?只是一个风格问题。使用
opendir
并不会神奇地使fs支持轮询。
dirfd(opendir(“…”)
更具可移植性,因此通常可能是首选。我是Linux内核黑客,所以我个人倾向于默认使用系统调用接口,即使它不是最合适的,因为我更了解它。显然在这里这并不重要,因为
epoll
也是Linux特有的。
/* The target file descriptor must support poll */
error = -EPERM;
if (!tfile->f_op || !tfile->f_op->poll)
    goto error_tgt_fput;