2013-04-04 86 views
0

我想监视我的系统上的USB密钥。我知道他们总是安装在/媒体上,所以我使用inotify监视/媒体。一些USB钥匙在插入时会创建一个文件夹(例如sda),直到它们被拔出,一些创建一个文件夹(例如sda),立即删除它并创建一个新文件夹(例如sda1)。这是由于密钥上的分区造成的。inotify缺失事件

但是,有时inotify只会捕获创建和删除第一个文件夹的事件,但会错过创建第二个文件夹的事件。当我手动检查/媒体时,第二个文件夹存在,但它从未通过inotify通知。

这种情况很少发生,当它发生时,它总是在重新启动后第一次插入设备。

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

/* size of the event structure, not counting name */ 
#define EVENT_SIZE (sizeof (struct inotify_event)) 

/* reasonable guess as to size of 32 events */ 
#define BUF_LEN  (32 * (EVENT_SIZE + 16)) 

int main(int argc, char **argv) { 
    int fd,wd,len,i; 
    char buf[BUF_LEN]; 
    struct inotify_event *event; 
    fd_set watch_set; 

    fd = inotify_init(); 
    if (fd < 0) { 
     perror("init failed"); 
     exit(EXIT_FAILURE); 
    } 

    wd = inotify_add_watch(fd,"/media",IN_ALL_EVENTS); 
    if (wd < 0) { 
     perror("add watch failed"); 
     exit(EXIT_FAILURE); 
    } 

    /* put the file descriptor to the watch list for select() */ 
    FD_ZERO(&watch_set); 
    FD_SET(fd,&watch_set); 

    while(1) { 
     select(fd+1,&watch_set,NULL,NULL,NULL); 
     len = read(fd,buf,BUF_LEN); 
     i=0; 
     while(i < len) { 

      event = (struct inotify_event *) &buf[i]; 

      if ((event->mask & IN_CREATE) != 0) { 
       printf ("%s created\n",event->name); 
      } 
      else if ((event->mask & IN_DELETE) != 0) { 
       printf ("%s deleted\n",event->name); 
      } 
      else { 
       printf ("wd=%d mask=0x%X cookie=%u len=%u name=%s\n", 
           event->wd, event->mask, 
           event->cookie, event->len, event->name); 
      } 

      i += EVENT_SIZE + event->len; 

     } 

    } 

} 

任何想法是怎么回事?

+0

它可以与http://stackoverflow.com/questions/15350369/how-to -use-inotify-in-c是'/ media'被删除,并且没有新的'inotify_add_watch'创建新的'/ media'? – 2013-04-04 10:01:58

+0

只有/ media的子文件夹被创建和删除。虽然一个事件被错过了,但下一个事件再次被捕获。所以手表仍在运行。 – bad 2013-04-04 10:53:03

回答

0

与此同时,我发现这是一个已知的inotify问题。如果两个事件几乎同时出现,则inotify只能捕获其中一个事件。 我的解决方案:我不再使用inotify,但采取libudev代替监视插入到机器的设备...

+3

任何参考? – zeekvfu 2013-12-02 02:29:40

1
  1. 可以使用inotifywait命令(从inotify-tools包)来监视/媒体目录,以检查是否inotify事件,利息确实发生你。
    参考:
    http://www.noah.org/wiki/Inotify,_FAM,_Gamin#Examples_with_inotify-tools

  2. 如果inotify不命中事件,其原因可能是:
    Inotify并报告一些但不是在sysfsprocfs所有事件。
    (好吧,我不能肯定地说只是我的猜测。)

参考:
http://en.wikipedia.org/wiki/Inotify#Limitations
http://en.wikipedia.org/wiki/Sysfs
http://en.wikipedia.org/wiki/Procfs

3

的子问题的inotify是众所周知的,容易被复制:

  1. 开始于otifywait观看空tmp目录:

    inotifywait -e创建-m -r --format '%:电子%F' ./tmp

  2. 在另一个壳输入:

    MKDIR TMP/0 TMP/0/0 TMP/0/0/0 TMP/0/0/0/0

  3. 您将最有可能只获得了第一个子目录的通知。

    创建:ISDIR 0

失去创建目录的时间之间的事件(特别是子目录创建事件)的不同的可能性,你的应用程序得到通知,并增加了新的inotify的手表,让递归监控太不可靠。唯一安全的选择是扫描新创建的目录的内容。

inotify doc限制和警告:那你的时间为 创建监视

如果监控整个目录树,和一个新的子目录 在树中创建,做到心中有数新的子目录中,新文件可能已经在 子目录中创建。因此,您可能需要在添加手表后立即扫描 子目录的内容。

+0

仔细观察bad的问题,他只关心一个目录级别,所以以上不适用。 – 2013-07-11 07:43:51

+0

但是,深入挖掘一下,这可能不是什么坏事: fd = inotify_init(); 如果使用select,这可能应该是: fd = inotify_init1(IN_NONBLOCK); 使用select,子目录事件立即收到,而不是缓冲。 – 2013-07-11 08:09:15

+0

正如你所提到的,子目录并不是什么让我感动的东西,我只对一个目录级别的事件感兴趣。然而,在此期间,我发现这是一个已知的inotify问题(请参阅我的回答) – bad 2013-07-12 07:47:14