3

我想监控我系统上的 USB 密钥。我知道它们总是挂载在 /media 中,所以我使用 inotify 来监控 /media。一些 USB Key 在插入时会创建一个文件夹(例如 sda),该文件夹会一直保留到拔出,有些则创建一个文件夹(例如 sda),然后立即删除它并创建一个新文件夹(例如 sda1)。这是由于密钥上的分区。

但是,有时 inotify 仅捕获创建和删除第一个文件夹的事件,而错过了第二个文件夹的创建。当我手动检查 /media 时,第二个文件夹存在,但 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;

        }

    }

}

任何想法出了什么问题?

4

3 回答 3

6

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

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

来自限制和警告下的inotify 文档

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

于 2013-07-11T06:55:25.923 回答
3

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

于 2013-07-12T07:50:46.017 回答
1
  1. 您可以使用inotifywait命令(从inotify-tools包中)监视/media目录,以检查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

于 2013-07-04T07:34:22.667 回答