inotify是否在写入开始或完成时触发通知?


12

想象一下两个进程,一个读取器和一个写入器,它们通过ext3 fs上的常规文件进行通信。Reader IN_MODIFY在文件上具有inotify 监视。Writer在单个write()调用中将1000字节写入文件。Reader获取inotify事件,然后调用fstat该文件。读者看到什么?

  1. 是否可以保证Reader至少可以取回st_size文件上的1000 ?从我的实验来看,似乎并非如此。

  2. 是否可以保证Reader可以实际读取read()1000个字节?

这是在严重的I / O绑定框中发生的。例如,sar显示大约1秒的等待时间。就我而言,阅读器实际上在获取inotify事件之后等待10秒钟stat,然后再调用,并且得到的结果太小。

我希望的是inotify事件在文件准备好之前不会传递。我怀疑实际上正在发生的是inotify事件write()在Writer中的调用期间触发,并且只要准备好了,数据实际上就可供系统上的其他进程使用。在这种情况下,10s是不够的时间。

我想我只是在寻找确认内核实际上实现了我所猜测的inotify方法。另外,是否有任何选择可以改变这种行为?

最后,鉴于这种行为,渗入的意义何在?在获得事件之后,您将减少为轮询文件/目录,直到实际可用数据为止。一直以来都应该这样做,而忽略了inotify。

*** 编辑 ** * * 好吧,就像我经常看到的那样,既然我了解自己的实际工作,那么我所看到的行为实际上是有道理的。^ _ ^

我实际上是在响应文件所在目录中的IN_CREATE事件。因此,实际上我是根据文件的创建来对文件进行stat()响应,而不一定是IN_MODIFY事件,后者可能会在以后到达。

我将更改代码,以便一旦获得IN_CREATE事件,便会订阅文件本身的IN_MODIFY,并且在获得IN_MODIFY事件之前,我实际上不会尝试读取文件。我意识到那里有一小窗口,我可能会错过对该文件的写操作,但这对于我的应用程序是可以接受的,因为在最坏的情况下,文件将在最大秒数后关闭。


您可以使用管道代替文件。看到男人mknod
丹尼尔·库尔曼2012年

我们需要使用一个常规文件,以便在两个进程之间具有一个数TB的缓冲区。还可以在重新启动时将数据保留在缓冲区中。
托德(Todd)在2012年

Answers:


5

根据我在内核源代码中看到的,inotify仅在写入完成后才会启动(即您的猜测是错误的)。触发通知后sys_write,在实现writesyscall 的函数中仅发生了另外两件事:设置一些调度程序参数,以及更新文件描述符上的位置。这段代码最早可以追溯到2.6.14。在通知触发时,文件已具有新大小。

检查可能出问题的地方:

  • 也许读者从以前的写作中得到了旧的通知。
  • 如果读者先打来电话stat,然后再打来电话,read反之亦然,则两者之间可能会发生某些情况。如果您继续追加到文件,则stat首先调用可以保证您能够读取该文件,但是read即使读者尚未收到inotify通知,也有可能在读者调用之时已经写入了更多数据。
  • 仅仅因为编写者调用write并不意味着内核将编写请求数量的字符。在极少数情况下,原子写保证可以达到任何大小。但是,每次write调用都保证是原子的:在某些时候尚未写入数据,然后突然写入了n个字节,其中nwrite调用的返回值。如果观察到部分写入的文件,则表示write返回的值小于其大小参数。

调查正在发生的事情的有用工具包括:

  • strace -tt
  • 审计子系统

谢谢你的想法。我刚刚检查了代码,实际上我只是检查-1作为错误情况下写入的返回值。因此,可能是我没有从写入中获得返回值,该值表明所有数据均已写入。但是,当我查看该文件之后,我知道实际上所有的“ 1000”字节都已写入,因为该文件的格式良好,即它由完整且一致的记录组成。因此,第一条记录没有被部分写入。
托德(Todd)在2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.