【问题标题】:How could I detect when a directory is mounted with inotify?如何检测目录何时使用 inotify 挂载?
【发布时间】:2010-11-09 22:26:45
【问题描述】:

我正在使用 Linux Inotify 来检测程序上的 FS 事件。

当设备挂载到受监控的目录时如何通知我?

【问题讨论】:

    标签: c linux kernel inotify


    【解决方案1】:

    我认为你不能用inotify 做到这一点。不过方法如下:

    1. 通过Netlink 套接字读取uevents from kernel 并过滤掉"ACTION" 不是"mount" 的那些。
    2. Read and parse "/proc/mounts" 当您收到带有 "mount" 操作的事件时。
    3. 查找刚刚挂载的设备的挂载点记录,如果不是您正在观看的目录,则将其过滤掉。

    【讨论】:

    • 另一种方法是在/etc/mtab 上放置一个inotify 手表,并进行与/proc/mounts 相同的解析。但这要脆弱得多。
    • 我不确定现在内核中有来自uevent 的任何mount 操作。好像是considered broken, and removed
    【解决方案2】:

    编辑:更新不到 5 年过时

    如果您使用的不是最古老的系统,libudev 就是您想要的第一步。

    如果您从事这十年的工作,udisks 也会为您完成所有这些工作。您需要观看/org/freedesktop/UDisks2 上的org.Freedesktop.DBus.ObjectManager 界面,以了解何时出现新的filesystems

    【讨论】:

      【解决方案3】:

      在现代 Linux 系统上 /etc/mtab 经常指向 /proc/self/mounts:

      $ ls -l /etc/mtab lrwxrwxrwx 1 root root 12 Sep 5 2013 /etc/mtab -> /proc/mounts $ ls -l /proc/mounts lrwxrwxrwx 1 root root 11 Jul 10 14:56 /proc/mounts -> self/mounts

      proc(5) manpage 说你真的不需要对这个文件使用 inotify,它是可轮询的:

      从内核版本 2.6.15 开始,这个 文件是可轮询的:打开文件进行读取后,更改 在这个文件中(即文件系统挂载或卸载)导致 select(2) 将文件描述符标记为可读,poll(2) 并且 epoll_wait(2) 将文件标记为有错误条件。

      想知道为什么 inotify 不能在 /etc/mtab 上运行并找到此手册页。

      【讨论】:

        【解决方案4】:

        inotify 只告诉你卸载,而 uevents 不再告诉你装载/卸载。

        这样做的方法是在 /proc/mounts 上进行轮询,读取内容,并跟踪您看到的挂载,然后在轮询唤醒时重新解析。当任何文件系统被挂载或卸载时,轮询将在 ERR/PRI 上唤醒。

        #include <fcntl.h>
        #include <errno.h>
        #include <poll.h>
        #include <unistd.h>
        #include <stdio.h>
        
        int main()
        {
            int fd;
            struct pollfd ev;
            int ret;
            ssize_t bytesread;
            char buf[8192];
        
            fd = open("/proc/mounts", O_RDONLY);
            printf("########################################\n");
            while ((bytesread = read(fd, buf, sizeof(buf))) > 0)
                write(1, buf, bytesread);
        
            do {
        
                ev.events = POLLERR | POLLPRI;
                ev.fd = fd;
                ev.revents = 0;
                ret = poll(&ev, 1, -1);
                lseek(fd, 0, SEEK_SET);
                if (ev.revents & POLLERR) {
                    printf("########################################\n");
                    while ((bytesread = read(fd, buf, sizeof(buf))) > 0)
                        write(1, buf, bytesread);
                }
            } while (ret >= 0);
            close(fd);
        
            return 0;
        }
        

        上面的代码只是在启动时打印出挂载点,然后在任何挂载/卸载时打印。您可以“区分”它们以找出添加/删除的内容。

        请注意,所有这些技术在过去的 Linux 版本中都不稳定和/或损坏。在 Linux 2.6.35 结束时(或者更早一点),这一切都变得稳定了。

        【讨论】:

          【解决方案5】:

          如果您不介意 大量 误报,您可以在 /etc/fstab 上关注 close_nowrite。 .观看/etc/mtab/proc/mounts 等对我不起作用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-04-15
            • 2011-01-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-17
            • 1970-01-01
            • 2019-02-08
            相关资源
            最近更新 更多