C语言中的inotify问题

3

我希望监控文件的修改,但是它不起作用。

示例输入:

./es file_to_watch

这是我的代码:

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

#define BUF_LEN sizeof(struct inotify_event) + NAME_MAX + 1 /*buffer to store the data of events*/

int main( int argc, char *argv[]){
   int fd, wd, length;
   char buffer[BUF_LEN];
   struct inotify_event *event;

   if(argc < 2){    
      exit(1);
   }
   else{
       fd = inotify_init();
       if(fd < 0){
           perror("inotify_init");
       }

       wd = inotify_add_watch(fd, argv[1], IN_OPEN | IN_MODIFY | IN_DELETE);
       if (wd == -1)
           return(1);
       else{

           while(1){
               length = read(fd, buffer, BUF_LEN); 
               if(length == -1)
                    return(0);

               event = (struct inotify_event *) &buffer;    
               if(event->len){
                    if(event->mask & IN_OPEN){
                         printf( "file %s was open.\n", event->name );
                    }
                    else if(event->mask & IN_MODIFY){
                        printf( "file %s was modify.\n", event->name );
                    }
                    else if(event->mask & IN_DELETE){
                        printf( "file %s was delete.\n", event->name );
                    break;
                    }
               }            
           }
           inotify_rm_watch(fd, wd);
           close(fd);
      }
  }
  return(0);
}

当我尝试打开文件时,什么都没有发生。当我尝试更改或取消它时,同样的事情也发生了。当文件被删除时,程序应该结束。 谢谢。
2个回答

2

以下是你需要解决的问题(来自inotify的man页面):

  1. name字段只在监视目录时存在。因此,在printf中使用event->name是错误的,你应该打印argv[1]
    The name field is present only when an event is returned for a file
    inside a watched directory; it identifies the file pathname relative
    to the watched directory.  This pathname is null-terminated, and may
    include further null bytes ('\0') to align subsequent reads to a
    suitable address boundary.

在您的情况下,event->mask永远不会等于IN_DELETE,因为
    IN_DELETE (+)
        File/directory deleted from watched directory.

  but instead

    IN_IGNORED
         Watch was removed explicitly (inotify_rm_watch(2)) or
         automatically (file was deleted, or filesystem was
         unmounted).  See also BUGS.

   when the file is deleted.

我建议您监视目录,并检查event->name是否与提供的argv [1]匹配。

此外,您应该在read后面添加一个循环,以读取所有可能的inotify_event *读取到的buffer。您可以通过在每次迭代中将指针增加sizeof(struct inotify_event)+ event->len 来完成。


1
是的,在调用read()后,您需要循环遍历inotify事件,并且此循环必须考虑到事件名称的不同长度。以下是这样一个循环的示例:http://www.enodev.fr/notifications-file-descriptors.html - Christophe Vu-Brugier

0

这个网站上有一个很好的例子:http://www.thegeekstuff.com/2010/04/inotify-c-program-example/

/*This is the sample program to notify us for the file creation and file deletion takes place in “/tmp” directory*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <linux/inotify.h>

#define EVENT_SIZE  ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )

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

  /*creating the INOTIFY instance*/
  fd = inotify_init();

  /*checking for error*/
  if ( fd < 0 ) {
    perror( "inotify_init" );
  }

  /*adding the “/tmp” directory into watch list. Here, the suggestion is to validate the existence of the directory before adding into monitoring list.*/
  wd = inotify_add_watch( fd, "/tmp", IN_CREATE | IN_DELETE );

  /*read to determine the event change happens on “/tmp” directory. Actually this read blocks until the change event occurs*/ 

  length = read( fd, buffer, EVENT_BUF_LEN ); 

  /*checking for error*/
  if ( length < 0 ) {
    perror( "read" );
  }  

  /*actually read return the list of change events happens. Here, read the change event one by one and process it accordingly.*/
  while ( i < length ) {     
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];         
if ( event->len ) {
  if ( event->mask & IN_CREATE ) {
    if ( event->mask & IN_ISDIR ) {
      printf( "New directory %s created.\n", event->name );
    }
    else {
      printf( "New file %s created.\n", event->name );
    }
  }
  else if ( event->mask & IN_DELETE ) {
    if ( event->mask & IN_ISDIR ) {
      printf( "Directory %s deleted.\n", event->name );
    }
    else {
      printf( "File %s deleted.\n", event->name );
    }
  }
}
i += EVENT_SIZE + event->len;
  }
  /*removing the “/tmp” directory from the watch list.*/
   inotify_rm_watch( fd, wd );

  /*closing the INOTIFY instance*/
   close( fd );

}

我已经看过这个例子,但是我在打开和修改文件方面遇到了问题。 - Francy Grillo
你是尝试了这个例子还是你的代码只是受到这段代码的启发? - Nicolas Charvoz
我有一个不同的问题,在这个例子中程序在一定数量的迭代后结束。我只想在检查的文件被删除时得到通知,这就是为什么我添加了 while (1),并且我也希望你能通知任何更改。 - Francy Grillo
@NicolasCharvozKurzawa,这并没有回答问题。 - Iharob Al Asimi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接