4

我正在尝试使用 inotify 来监视文件以在无限循环中进行修改。我遇到了一些问题:

1)我有一个while(1),除非我为while的每次迭代创建一个新的文件描述符和一个新的监视描述符(我想要做的是在无限循环之前打开这些描述符),否则读取不起作用,但如果其他解决方案是可以接受的,那么我可以使用它)。这是有效的版本:

 while(1){
    int file_descriptor = inotify_init();
    if (file_descriptor < 0) {
        perror("inotify_init");
    }

    int watch_descriptor = inotify_add_watch(file_descriptor, "/home/user/hello.cfg", IN_CLOSE_WRITE);
    ....

2)我尝试使用掩码IN_MODIFY,但我读到它不适用于vim,所以我改用IN_CLOSE_WRITE。问题是当我用vim修改文件时,会读取事件,但事件的掩码是IN_IGNORED(掩码0x00008000)。当我使用gedit时,有时事件的掩码是IN_IGNORED,有时是IN_CLOSE_WRITE(掩码0x0000008)。我想知道如果我正在修改文件,为什么会得到 IN_IGNORED,以及为什么事件不是 IN_CLOSE_WRITE。是否有另一种方法来监视单个文件的修改?IN_CLOSE_WRITE 是正确的掩码吗?

4

1 回答 1

1

我在编写一个守护程序时发现了相同的行为(内核 3.14.4),如果在运行时发生更改,它会自动重新加载其配置文件。我发现某些程序(其中包括 vim)导致 inotify 生成 IN_IGNORED,因为它们删除了原始文件并将其替换为“交换”文件。

从 inotify 文档中,

       IN_IGNORED
              Watch was removed explicitly (inotify_rm_watch(2)) or
              automatically (file was deleted, or filesystem was
              unmounted).  See also BUGS.

您可以通过运行看到这一点

strace -o log vi myfile.txt

并检查日志中的 strace 结果,这将显示 .myfile.txt.swp 的创建和删除。

解决方案是捕获 IN_IGNORED 事件并为您的文件重新添加监视,即

int watch_descriptor = inotify_add_watch(file_descriptor, "/home/user/hello.cfg", (IN_CLOSE_WRITE | IN_IGNORED));

IN_CLOSE_WRITE 是要处理的正确事件,但也有一个陷阱。有些程序打开一个文件进行读写,但只从中读取。当他们关闭文件时,即使文件没有被修改,也会生成 IN_CLOSE_WRITE。

我发现最好的方法是为我正在观看的每个文件维护一个标志,并在我捕获 IN_MODIFY 时切换它。然后,当生成 IN_CLOSE_WRITE 时,可以检查该标志以确定 IN_CLOSE_WRITE 是否有意义。

于 2014-06-05T11:16:28.983 回答