2013-04-04 2 views
0

Я хочу контролировать USB-ключи в своей системе. Я знаю, что они всегда монтируются в/media, поэтому я использую inotify для мониторинга/мультимедиа. Некоторые USB-ключи создают папку (например, sda) при подключении, которая остается до тех пор, пока они не будут отключены, некоторые создадут папку (например, sda), удаляют ее сразу и создают новую (например, sda1). Это связано с разделами на ключе.inotify missing events

Однако иногда 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', и создается новый'/media', для которого не создано никакого нового 'inotify_add_watch'? –

+0

Создаются и удаляются только подпапки/media. Несмотря на то, что событие было пропущено, следующий снова зацепился. Таким образом, часы все еще работают. – bad

ответ

0

Между тем я обнаружил, что это известная проблема inotify. Если два события появляются практически одновременно, inotify только ловит один из них. Мое решение: я больше не использую inotify, но вместо этого взял libudev, чтобы контролировать устройства, подключенные к машине ...

+3

Любые ссылки? – zeekvfu

1
  1. Вы можете использовать inotifywait команду (из inotify-tools пакета) для контроля за /медиа- каталог для того, чтобы проверить, соответствуют ли inotify события, которые происходят интерес вы.
    ссылка:
    http://www.noah.org/wiki/Inotify,_FAM,_Gamin#Examples_with_inotify-tools

  2. Если inotify делает несоосности события, причиной может быть:
    Inotify делает доклад некоторые, но не все события в sysfs и procfs.
    (Ну, я не могу точно сказать, только мое предположение..)

Ссылка:
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 '%: е% п' ./tmp

  2. В другой оболочки входят:

    MkDir TMP/0 tmp/0/0 tmp/0/0/0 tmp/0/0/0/0

  3. Скорее всего, вы получите уведомление только для первого подкаталога.

    СОЗДАТЬ: ISDIR 0

Явная возможность потери событий (в частности подкаталог события создания) между временем создаются каталог, ваше приложение получает уведомление, и новый Inotify часы добавляют, делает рекурсивным мониторинг слишком ненадежный. Единственным безопасным вариантом является сканирование содержимого вновь созданных каталогов.

Из inotify doc под Ограничения и предостережения:

Если контроль весь каталог поддерева, и новый подкаталог создается в этом дереве, следует помнить, что к тому времени, вы создаете часы для новый подкаталог, новые файлы, возможно, уже были созданы в подкаталоге . Поэтому вам может потребоваться отсканировать содержимое подкаталога сразу после добавления часов.

+0

Более пристально глядя на проблему плохого, он касается только одного уровня каталогов, поэтому вышеприведенное не применяется. –

+0

Однако, копая немного глубже, это может быть не то, что нужно: fd = inotify_init(); При использовании select это должно быть: fd = inotify_init1 (IN_NONBLOCK); С помощью select события подкаталога принимаются немедленно, а не буферизируются. –

+0

Как вы уже упоминали, подкаталоги были не то, что меня возбуждало, меня интересовали только события на одном уровне каталога. Тем не менее, в то время я обнаружил, что это известная проблема inotify (см. Мой ответ) – bad

Смежные вопросы