1

我使用 kqueues/kevent(2) 在单独的线程中监视文件的更改。(我监控一个 Python 文件进行重新解析)

我订阅如下:

EV_SET(&file_change, pyFileP, EVFILT_VNODE,
       EV_ADD | EV_CLEAR,
       NOTE_DELETE |  NOTE_WRITE | NOTE_EXTEND | 
               NOTE_ATTRIB | NOTE_LINK | NOTE_RENAME | NOTE_REVOKE,
       0, 0);

当我使用 Vim 写入文件“/tmp/somefile.py”时,我得到两个单独的 kevent: 这些事件的标志 (event.fflags) 是:

NOTE_RENAME

NOTE_DELETE | NOTE_LINK

我从来没有收到过“NOTE_WRITE”事件!这似乎与 Vim 写入这些文件的方式有关,因为如果我这样做了

echo "sometext" >> /tmp/somefile.py

我确实得到了:

NOTE_WRITE|NOTE_EXTEND

事件。

奇怪,嗯?我没有检查 Vim 源代码,但它必须做一些奇怪的事情,或者它只是使用以这种方式实现的用户级函数?

我真的没想到会这样。这是一个已知问题,我只需要检查所有可能的事件,还是有一个已知的接口可以真正检查文件是否已被写入?

4

1 回答 1

1

实际发生的情况是 Vim 不会覆盖同一个文件,首先它可能会将其重命名为其他文件,然后创建另一个文件(链接)。您可以通过执行以下操作来确认:

$ vim file -c wq

这将打开一个文件并写入它。现在检查 inode:

$ ls -i
30621217 file

再次用 Vim 写入文件并重新检查 inode:

$ vim file -c wq
$ ls -i
30621226 file

只是不一样。这意味着第二个文件实际上是另一个同名文件(链接到另一个 inode),而旧文件未链接。

许多编辑都这样做。我无法确认 Vim 究竟为何采用这种方法。 也许为了安全起见:如果您首先重命名文件并且在编写新文件时出现问题,您仍然拥有旧文件。如果您开始写入文件并出现问题(即使是内存),您可能会丢失其中的一部分。也许

于 2011-11-28T16:45:46.617 回答