当前位置:首页>Linux>Linux inotify 实现文件系统监控

Linux inotify 实现文件系统监控

  • 2026-10-21 13:29:00
Linux inotify 实现文件系统监控

    感兴趣Linux底层驱动可以私信我:

    2026打造你的职场核心竞争力(linux系统技术栈)

    文章目录

    • 一、inotify 底层实现原理
    • 二、系统限制

    📢本篇将详细介绍 Linux 中用 inotify 实现文件系统监控在内核中的实现思路。

    一、inotify 底层实现原理


    不管是单个文件,还是某个目录,在 Linux 的文件系统上,都会对应一个索引节点(inode),所以,不管是在某个目录下新建或修改文件,或者修改某个文件对应的内容,都会执行 inode 信息的更新。所以,inode 是理想的文件系统事件的监测点。

    在 inode 的数据结构中,有两个字段用来记录当前的文件事件观察者:

    __u32    i_fsnotify_mask;//对当前节点感兴趣的所有事件掩码
    structhlist_head    i_fsnotify_marks;//监控当前节点的所有监控对象,fsnotify_mark 结构的链表  

    在执行 inotify_add_watch() 时,就是在上面的监控列表对象上追加或更新项目。

    在 fsnotify_mark 结构中,比较重要的字段包括:

    structfsnotify_mark{
        __u32 mask;// 感兴趣的事件掩码
    structfsnotify_group*group;//指向包含本监控项的监控对象
    union{
    structfsnotify_inode_mark i;//索引到相关的 inode
    structfsnotify_vfsmount_mark m;
    };
    ......
    };

    其中的 group 字段,就是在 inotify_init() 创建监控对象时生成的内核数据结构,其中包含了添加到这个监控对象上的所有监控项的列表、阻塞 read() 系统调用的读队列,以及产生的通知事件列表,等等。

    structfsnotify_group{
    structlist_head notification_list;//要发到用户空间的事件列表
    wait_queue_head_t notification_waitq;//阻塞 read() 系统调用的等待队列
    unsignedint q_len;//等待队列长度
    unsignedint max_events;//队列中允许保存的事件的最大数量
    atomic_t num_marks;//监控目标数量
    structlist_head marks_list;//监控目标列表
    ......
    };

    用一个示例表示上面各个结构间的关系:

    在这个例子中,有两个监控对象,分别创建了对应的内核对象结构:

    • fsnotify_group1
    • fsnotify_group2

    其中 fsnotify_group1 只有一个监控目标 inode1,而 fsnotify_group2 有两个监控目标:inode1 和 inode2。

    当 inode1 或 inode2 上发生了文件系统事件时,分别沿着绿色和蓝色的箭头就可以定位到需要唤醒并通知的阻塞 read()。

    二、系统限制


    可以看到,某个 inode 被添加为监控目标后,当在该 inode 上发生任何文件事件时,是可以 O(1) 地定位到相关的阻塞 read(),从而向应用层发出事件通知的。

    虽然如此,但是我们同时也能看到,每个监控对象和监控目标都需要分配相应的内核数据结构,这会占用内核空间的内存。

    为了保护系统,Linux 对系统中的文件系统监控实例的数量,以及每个实例中可以监控的目标的数量都做了限制,实际的限制值可以在位于目录 /proc/sys/fs/inotify 下的几个文件中查看和设置,每个文件代表的意义见下说明。

    • max_user_instances:允许用 inotify_init() 创建的监控对象的最大数量,默认为 128。

    • max_user_watches:每个监控对象中,可以用 inotify_add_watch() 添加的监控目标的最大数量,默认为 8192。

    • max_queued_events:每个监控对象上,在调用 read() 之前能够排队的事件的最大数量,超出这个数量的事件会被丢弃,默认值为 16384。

    最新文章

    随机文章