inotify缺少事件

时间:2013-04-04 08:48:01

标签: c linux inotify

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

但是,有时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;

        }

    }

}

任何想法出了什么问题?

3 个答案:

答案 0 :(得分:4)

inotify的子文件夹问题众所周知,很容易复制:

  1. 启动inotifywait,观看一个空的tmp目录:

    inotifywait -e create -m -r --format'%:e%f'。/ tmp

  2. 在另一个shell中输入:

    mkdir tmp / 0 tmp / 0/0 tmp / 0/0/0 tmp / 0/0/0/0

  3. 您很可能只会收到第一个子目录的通知。

    创建:ISDIR 0

  4. 在创建目录,通知应用程序以及添加新的inotify监视之间丢失事件(特别是子目录创建事件)的独特可能性使得递归监视太不可靠。唯一安全的选择是扫描新创建的目录的内容。

    来自限制和警告下的inotify doc

      

    如果监视整个目录子树,并且是一个新的子目录   在该树中创建,请注意,当您为其创建手表时   在新的子目录中,可能已经在新的文件中创建了新文件   子目录。因此,您可能想要扫描内容   添加手表后立即进行子目录。

答案 1 :(得分:1)

  1. 您可以使用inotifywait命令(来自inotify-tools包)来监控 / media 目录,以检查inotify是否inotify你感兴趣的事件 参考:
    http://www.noah.org/wiki/Inotify,_FAM,_Gamin#Examples_with_inotify-tools

  2. 如果Inotify确实错过了活动,原因可能是:
    sysfs会报告procfs和{{1}}中的部分但非全部事件 (好吧,我不能肯定地说。只是我的猜测。)

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

答案 2 :(得分:0)

同时我发现这是一个已知的inotify问题。如果两个事件几乎同时出现,则inotify仅捕获其中一个事件。 我的解决方案:我不再使用inotify,而是使用libudev来监控插入机器的设备......