土法炼钢兴趣小组的算法知识备份

【操作系统百科】文件变化通知

文章导航

分类入口
os
标签入口
#inotify#fanotify#fsnotify#dnotify#file-watch

目录

文件编辑器要感知外部修改、搜索引擎要索引新文件、杀毒软件要扫描打开的文件——都需要”文件变化通知”。Linux 经历了 dnotify → inotify → fanotify 三代。

一、先看图

flowchart LR
    VFS[VFS 操作<br/>create/write/rename...] --> FSN[fsnotify 框架]
    FSN --> INOT[inotify 后端<br/>per-watch fd]
    FSN --> FAN[fanotify 后端<br/>per-mount/sb]
    FSN --> AUDIT[audit 后端]
    INOT --> APP1[用户进程<br/>read 事件]
    FAN --> APP2[用户进程<br/>read + 拦截]
    classDef kern fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    classDef user fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    class VFS,FSN kern
    class INOT,FAN,AUDIT kern
    class APP1,APP2 user

二、fsnotify 内核框架

所有文件通知共享 fsnotify 基础设施:

三、dnotify(已废弃)

fcntl(dirfd, F_NOTIFY, DN_MODIFY | DN_CREATE);

缺点:只能监控目录 fd、用 signal 通知(不安全)、不告诉你是哪个文件变了。

四、inotify

4.1 API

int ifd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
int wd = inotify_add_watch(ifd, "/tmp", IN_CREATE | IN_MODIFY | IN_DELETE);
// read(ifd, buf, ...) → struct inotify_event
inotify_rm_watch(ifd, wd);

4.2 优势

4.3 限制

4.4 递归监控

应用需要手动递归添加 watch → 大目录树要加几万个 watch → 消耗内存(每 watch ~1KB 内核内存)。

sysctl fs.inotify.max_user_watches=524288

VS Code、IntelliJ、webpack 都靠 inotify。

五、fanotify

5.1 特点

5.2 API

int fan_fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_REPORT_FID, O_RDONLY);
fanotify_mark(fan_fd, FAN_MARK_ADD | FAN_MARK_FILESYSTEM,
    FAN_CREATE | FAN_DELETE | FAN_MODIFY | FAN_ONDIR,
    AT_FDCWD, "/mnt");
// read(fan_fd, buf, ...) → struct fanotify_event_metadata

5.3 拦截模式

// 读到 FAN_OPEN_PERM 事件
struct fanotify_response resp = {
    .fd = event->fd,
    .response = FAN_ALLOW,  // 或 FAN_DENY
};
write(fan_fd, &resp, sizeof(resp));

杀毒软件(ClamAV on-access scanner)用这个。

5.4 FAN_REPORT_FID

fanotify_init(FAN_REPORT_FID | FAN_REPORT_DIR_FID | FAN_REPORT_NAME, ...);

事件包含目录 file handle + 文件名 → 可以定位到完整路径,不需要 per-directory watch。

六、对比

特性 dnotify inotify fanotify
粒度 目录 目录(+文件名) mount/sb/文件系统
递归 手动 FAN_REPORT_FID 原生
拦截 FAN_*_PERM
通知方式 signal fd (read) fd (read)
权限 用户 用户 需要 CAP_SYS_ADMIN

七、高频场景与 overflow

npm install 创建几万文件 → inotify 事件风暴 → queue overflow。

缓解:

八、audit 联动

audit 子系统也用 fsnotify:

auditctl -w /etc/passwd -p wa -k passwd_changes

每次写 /etc/passwd 产生 audit 记录。与 inotify/fanotify 并行。

九、观察

# inotify watch 使用
find /proc/*/fdinfo -name '*' -exec grep -l inotify {} \; 2>/dev/null
cat /proc/sys/fs/inotify/max_user_watches

# fanotify
cat /proc/sys/fs/fanotify/max_user_marks

十、小结


参考文献

工具


上一篇xattr/ACL/capabilities 下一篇OverlayFS

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。

2026-04-28 · os

【操作系统百科】交换

swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。

2026-05-03 · os

【操作系统百科】Slab/SLUB 分配器

buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。

2026-05-07 · os

【操作系统百科】用户态分配器

glibc malloc、tcmalloc、jemalloc、mimalloc 各有哲学。本文讲 arena、thread cache、size class、madvise 返还策略、碎片与 RSS 膨胀、如何根据负载选分配器。


By .