简体   繁体   English

多次错误地通知新文件

[英]inotify notifies of a new file wrongly multiple times

Using inotify to monitor a directory for any new file created in the directory by adding a watch on the directory by 使用inotify监视目录中目录中创建的任何新文件,方法是在目录上添加监视

    fd = inotify_init();
    wd = inotify_add_watch(fd, "filename_with_path", IN_CLOSE_WRITE);
    inotify_add_watch(fd, directory_name, IN_CLOSE_WRITE);

    const int event_size = sizeof(struct inotify_event);
    const int buf_len = 1024 * (event_size + FILENAME_MAX);
    while(true) {
        char buf[buf_len];
        int no_of_events, count = 0;
        no_of_events = read(fd, buf, buf_len);
        while(count < no_of_events) {
            struct inotify_event *event = (struct inotify_event *) &buf[count];
            if (event->len) {
                if (event->mask & IN_CLOSE_WRITE) {
                    if (!(event->mask & IN_ISDIR)) {
                         //It's here multiple times 
                    }
                }
            }
            count += event_size + event->len;
        }

When I scp a file to the directory, this loops infinitely. 当我将文件压缩到目录中时,这将无限循环。 What is the problem with this code ? 此代码有什么问题? It shows the same event name and event mask too. 它也显示相同的事件名称和事件掩码。 So , it shows that the event for the same, infinite times. 因此,它表明事件发生了相同的无限次。

There are no break statements . 没有break语句 If I find an event, I just print it and carry on waiting for another event on read(), which should be a blocking call. 如果找到一个事件,则只打印它并继续在read()上等待另一个事件,这应该是阻塞调用。 Instead, it starts looping infinitely. 相反,它开始无限循环。 This means, read doesn't block it but returns the same value for one file infinitely. 这意味着,read不会阻止它,但是会无限期地为一个文件返回相同的值。

This entire operation runs on a separate boost::thread. 整个操作在单独的boost :: thread上运行。

EDIT: Sorry all. 编辑:对不起。 The error I was getting was not because of the inotify but because of sqlite which was tricky to detect at first. 我得到的错误不是因为inotify而是因为sqlite首先很难检测到。 I think I jumped the gun here. 我想我在这里开枪了。 With further investigation, I did find that the inotify works perfectly well. 经过进一步的调查,我确实发现inotify效果很好。 But the error actually came from the sqlite command : ATTACH 但是错误实际上来自sqlite命令: ATTACH

That command was not a ready-only command as it was supposed to. 该命令不是应有的仅准备就绪的命令。 It was writing some meta data to the file. 它正在将一些元数据写入文件。 So inotify gets notification again and again. 因此,inotify一次又一次地得到通知。 Since they were happening so fast, it screwed up the application.I finally had to breakup the code to understand why. 因为它们发生得如此之快,所以它弄糟了应用程序。我最终不得不分解代码以了解原因。

Thanks everyone. 感谢大家。

I don't see anything wrong with your code...I'm running basically the same thing and it's working fine. 我看不到您的代码有什么问题...我基本上在运行同一件事,并且工作正常。 I'm wondering if there's a problem with the test, or some part of the code that's omitted. 我想知道测试是否有问题,或者代码的某些部分被遗漏了。 If you don't mind, let's see if we can remove any ambiguity. 如果您不介意,让我们看看是否可以消除任何歧义。

Can you try this out (I know it's almost the same thing, but just humor me) and let me know the results of the exact test? 您可以尝试一下(我知道这几乎是同一件事,但只是逗我笑),并让我知道确切测试的结果吗?

1) Put the following code into test.c 1)将以下代码放入test.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/inotify.h>

int main (int argc, char *argv[])
{
   char target[FILENAME_MAX];
   int result;
   int fd;
   int wd;   /* watch descriptor */
   const int event_size = sizeof(struct inotify_event);
   const int buf_len = 1024 * (event_size + FILENAME_MAX);

   strcpy (target, ".");

   fd = inotify_init();
   if (fd < 0) {
      printf ("Error: %s\n", strerror(errno));
      return 1;
   }

   wd = inotify_add_watch (fd, target, IN_CLOSE_WRITE);
   if (wd < 0) {
      printf ("Error: %s\n", strerror(errno));
      return 1;
   }

   while (1) {
     char buff[buf_len];
     int no_of_events, count = 0;

     no_of_events = read (fd, buff, buf_len);

     while (count < no_of_events) {
       struct inotify_event *event = (struct inotify_event *)&buff[count];

       if (event->len){
         if (event->mask & IN_CLOSE_WRITE)
           if(!(event->mask & IN_ISDIR)){
              printf("%s opened for writing was closed\n", target);
              fflush(stdout);
           }
       }
       count += event_size + event->len;
     }
   }

   return 0;
}

2) Compile it with gcc: 2)用gcc编译:

gcc test.c

3) kick it off in one window: 3)在一个窗口中将其启动:

./a.out

4) in a second window from the same directory try this: 4)在同一目录的第二个窗口中尝试以下操作:

echo "hi" > blah.txt

Let me know if that works correctly to show output every time the file is written to and does not loop as your code does. 让我知道每次写入文件时该方法是否都能正常显示输出,并且不会像您的代码那样循环播放。 If so, there's something important your omiting from your code. 如果是这样,则有一些重要的事情需要您从代码中删除。 If not, then there's some difference in the systems. 如果没有,那么系统之间会有一些差异。

Sorry for putting this in the "answer" section, but too much for a comment. 抱歉,将其放在“答案”部分,但太多了,无法发表评论。

我的猜测是read返回-1,并且由于您从未尝试修复错误,因此在下一次调用read时又遇到了另一个错误,该错误也返回-1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM