使丢失的事件发声

bad*_*bad 1 c linux inotify

我想监视系统上的USB密钥。我知道它们总是安装在/ media中,因此我使用inotify监视/ media。一些USB钥匙在插入时会创建一个文件夹(例如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;

        }

    }

}
Run Code Online (Sandbox Code Playgroud)

任何想法出什么事了吗?

Pet*_*vic 5

inotify的子文件夹问题是众所周知的,并且很容易重现:

  1. 开始inotifywait观看一个空的tmp目录:

    inotifywait -e创建-m -r --format'%:e%f'./tmp

  2. 在另一个外壳中输入:

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

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

    创建:ISDIR 0

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

inotify文档的限制和警告”下

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