2013-04-04 88 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