Inotify - 强大而简单的文件更改通知系统

文档由 Robert Love 于 2005 年 3 月 15 日开始编写 <rml@novell.com>

文档由 Zhang Zhen 于 2015 年 1 月 4 日更新 <zhenzhang.zhang@huawei.com>

  • 删除了过时的接口,请参考手册页了解用户界面。

  1. 原理

为什么不将监视绑定到被监视对象的打开 fd 上?

监视与打开的 inotify 设备相关联,而不是与打开的文件相关联。 这解决了 dnotify 的主要问题:保持文件打开会锁定文件,更糟糕的是,还会锁定挂载点。 因此,Dnotify 对于具有可移动媒体的桌面系统是不可行的,因为无法卸载媒体。 监视文件不应要求它处于打开状态。

为什么使用每个实例一个 fd,而不是每个监视一个 fd?

每个监视一个 fd 很快就会消耗比允许的更多的文件描述符,比管理可行的更多的 fd,以及比最佳 select()-able 更多的 fd。 是的,root 可以提升每个进程的 fd 限制,是的,用户可以使用 epoll,但要求两者都是愚蠢且无关的要求。 监视消耗的内存比打开的文件少,因此,分离数字空间是有意义的。 当前的设计是用户空间开发人员想要的:用户初始化 inotify 一次,并添加 n 个监视,但只需要一个 fd,无需调整 fd 限制。 初始化一个 inotify 实例两千次是很愚蠢的。 如果我们可以干净地实现用户空间的偏好——我们可以,idr 层使此类事情变得微不足道——那么我们应该这样做。

还有其他好的论点。 使用单个 fd,只有一个项目可以阻塞,该项目映射到单个事件队列。 单个 fd 返回所有监视事件以及任何潜在的带外数据。 如果每个 fd 都是单独的监视,

  • 将无法获得事件排序。 文件 foo 和文件 bar 上的事件会弹出 poll() 在两个 fd 上,但是无法分辨哪个先发生。 单个队列可以轻松地为您提供排序。 这种排序对于 Beagle 等现有应用程序至关重要。 想象一下没有排序的“mv a b ; mv b a”事件。

  • 我们将不得不维护 n 个 fd 和 n 个带有状态的内部队列,而不是只有一个。 在内核中会更加混乱。 单个线性队列是有意义的数据结构。

  • 用户空间开发人员更喜欢当前的 API。 例如,Beagle 的人们喜欢它。 相信我,我问过了。 这并不奇怪:谁愿意通过 select 管理和阻塞 1000 个 fd?

  • 无法获得带外数据。

  • 1024 仍然太低了。 ;-)

当您谈论设计一个可扩展到数千个目录的文件更改通知系统时,处理数千个 fd 似乎不是正确的接口。 它太重了。

此外,_是_可以拥有多个实例并处理多个队列,因此可以处理多个关联的 fd。 不需要每个进程一个 fd 的映射; 它是每个队列一个 fd,并且一个进程很容易需要多个队列。

为什么采用系统调用方法?

糟糕的用户空间接口是 dnotify 的第二大问题。 信号是文件通知的糟糕、糟糕的接口。 或者对于任何事情,就此而言。 从所有角度来看,理想的解决方案是基于文件描述符的解决方案,该解决方案允许基本的文件 I/O 和 poll/select。 获取 fd 和管理监视可以通过设备文件或一系列新的系统调用来完成。 我们决定实现一系列系统调用,因为这是新内核接口的首选方法。 唯一的真正区别是我们是否想使用 open(2) 和 ioctl(2) 或几个新的系统调用。 系统调用优于 ioctls。