inotify 是否同步排队事件?

Does inotify enqueue events synchronously?

我正在尝试使用 inotify 来监视文件系统修改。特别是我正在尝试捕获某个预配置目录中文件的所有更新。

当我尝试使用 SIGTERM 关闭应用程序时出现了问题。我希望在此之前处理所有修改。

问题: 如果唯一进行文件修改(writeing/mving)的进程终止是否可靠地说如果 FIONREAD ioctl returns 0 那么所有修改都是从 inotify 文件描述符中检索的。 The documentation 指定:

The FIONREAD ioctl(2) returns the number of bytes available to read from an inotify file descriptor.

所以我假设如果在执行所有修改的进程关闭后队列中没有留下任何事件,那么所有事件都会从 inotify 描述符中读取,并且以后不会有人到达。

我强烈建议您使用 signalfd,请参阅 this man page

有了这个信号,信号就会沿着管道传递,而不是信号动作是 运行 异步的。这样你就可以使用像 select()epoll() 这样的反应堆来等待 inotify 管道和 signalfd() 文件描述符,允许你在实际从 fd 读取信号时进行整洁管理并处理它。

而且,因为您是在程序的主循环内同步处理信号,而不是在异步信号操作中,所以在处理信号时可以调用哪些函数没有限制。

以我的拙见,signalfd() 远远优于处理信号的令人讨厌的旧方法。唯一的小缺点是它(据我所知)不能移植到其他 *nixes。

这个问题和公认的答案中有几件事被混淆了。

回答问题的核心:

如果正在更改监视位置中的文件的唯一进程已终止,那么您可以在 inotify 队列中没有更多事件时终止。您可以通过检查问题中提到的 FIONREAD 来安全地检查大小。为了不遗漏任何事件,您需要通过其他方式确定变异过程已经完成;这个的关键方面是你不想在变异过程完成之前完成处理 inotify 队列,并且你的 inotify 进程已经收到 SIGTERM.

但是,如果您不知道其他进程是否已完成,但想确保到当前时间点(例如:检测到 SIGTERM 时)的事件已被处理,您将需要使用类似于 watchman 中使用的技术。这个概念是当您的主进程被要求终止时,您将在监视目录中创建一个具有神奇名称的特殊标记文件。然后你将继续处理来自 inotify 队列的事件,直到你看到你的魔法文件名;在这一点上,您可以知道创建魔术文件之前的所有事件都已被消耗。这里有关于此技术的更多信息:https://facebook.github.io/watchman/docs/cookies.html(免责声明:我是守望者的创造者)

关于 signalfd 与传统信号处理的讨论与这个问题的时序方面是正交的:您当然可以使用原始的 posix 信号处理接口并设置一个全局变量来指示SIGTERM 已收到。它不会改变 inotify 事件的顺序或时间安排,所以在实现时可以随意使用任何你喜欢的方法。