【问题标题】:inotify watcher stops working after ls or watch commandsinotify watcher 在 ls 或 watch 命令后停止工作
【发布时间】:2014-03-14 06:30:17
【问题描述】:

我从互联网上的many examples 中获取了关于如何使用inotify 的以下代码。

然后我尝试了以下实验:
1) 在下面运行观察者
2) 在一个单独的外壳中,cd 进入'/mypath' 为您正在观看的文件夹创建一些文件。例如,'date > output.txt' 一次或多次。
3) 您将看到来自观察者的通知。
4)输入'ls /mypath'(甚至'watch -n 1 /mypath'
5) 在/mypath 中尝试'date > output.txt'。您将不再看到来自观察者的通知。或者至少,这是我使用 Ubuntu 12/13 测试时发生的情况。

关于如何修复它的任何想法?

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <limits.h>
#include <unistd.h>


#define MAX_EVENTS 1024 /*Max. number of events to process at one go*/
#define LEN_NAME 16 /*Assuming that the length of the filename won't exceed 16 bytes*/
#define EVENT_SIZE  ( sizeof (struct inotify_event) ) /*size of one event*/
#define BUF_LEN     ( MAX_EVENTS * ( EVENT_SIZE + LEN_NAME )) /*buffer to store the data of events*/

int main() 
{
  int length, i = 0, wd;
  int fd;
  char buffer[BUF_LEN];

  /* Initialize Inotify*/
   fd = inotify_init();
  if ( fd < 0 ) {
    perror( "Couldn't initialize inotify");
  }

  /* add watch to starting directory */
  wd = inotify_add_watch(fd, "/mypath", IN_CLOSE_WRITE | IN_CLOSE_NOWRITE); 

  if (wd == -1)
    {
      printf("Couldn't add watch to %s\n","/mypath");
    }
  else
    {
      printf("Watching:: %s\n","/mypath");
    }

  /* do it forever*/
  while(1)
    {  
      i = 0;
      length = read( fd, buffer, BUF_LEN );  


      if ( length < 0 ) {
        perror( "read" );
      }  

      while ( i < length ) {
        struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
        if ( event->len ) {
          if ( event->mask & IN_CLOSE_WRITE) {
            if (event->mask & IN_ISDIR)
              printf( "The directory %s was Created.\n", event->name );       
            else
              printf( "The file %s was closed (write) with WD %d\n", event->name, event->wd );       
          }
          if ( event->mask & IN_CLOSE_NOWRITE) {
            if (event->mask & IN_ISDIR)
              printf( "The directory %s was Created.\n", event->name );       
            else
              printf( "The file %s was closed (nowrite) with WD %d\n", event->name, event->wd );       
          }



          i += EVENT_SIZE + event->len;
        }
      }     
    }

  /* Clean up*/
  inotify_rm_watch( fd, wd );
  close( fd );

  return 0;
}

【问题讨论】:

  • 您可以尝试使用inotifywait 命令行(对于inotify-tools 包中的ubuntu)而不是您自己的可执行文件吗?
  • 不要忘记通过点击您所选答案的勾下的 +200 来奖励赏金!

标签: c++ linux inotify


【解决方案1】:

您不应将i += EVENT_SIZE + event-&gt;len; 放在if ( event-&gt;len ) 块内。如果事件的名称长度为零,则指针仍应增加EVENT_SIZE(如果将该语句放在块外会发生这种情况)。我认为您可能会在您的 inotify 程序中看到一个无限循环,该循环由第一个恰好具有零长度名称的事件开始。 (这正是ls 发生的情况:正在打开目录,而不是其文件,因此name 字段中没有任何内容。)

【讨论】:

  • 所以基本上你建议把它放在上面代码中的括号后面吧?
【解决方案2】:

你进入了一个永无止境的循环,因为你没有改变ievent-&gt;len == 0 添加这个:

else
    i += EVENT_SIZE ;

万一if ( event-&gt;len == 0 )

【讨论】:

  • 这肯定会让事情变得更糟。 i 是一个字节计数器。它不索引事件。
【解决方案3】:

事实证明,当您的程序停止工作时,它会占用所有 CPU。我做了一些更改,现在似乎可以使用了。以下是详细信息:

声明 BUF_LEN 处理 16 个事件(您可以增加该值):

#define BUF_LEN (16 * (sizeof(struct inotify_event) + NAME_MAX + 1))

将处理事件的 while (i &lt; length) 循环更改为以下 for 循环:

for ( p = buffer; p < buffer + length; ) {
    struct inotify_event *event = ( struct inotify_event * ) p;
    p += sizeof(struct inotify_event) + event->len;
    if ( event->len ) {
        /* SNIP */
    }
}

p 变量应声明为char *,您可以删除不再使用的i

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    相关资源
    最近更新 更多