linux-如何在功能测试中模拟INotify失败?

我有一个使用inotify跟踪文件系统更改的Linux应用程序.我想为此编写一个功能测试套件,以从最终用户的角度测试应用程序,作为测试的一部分,我想测试文件系统出现故障的情况,尤其是要测试inotify失败.
特别是,我想对inotify文件描述符进行inotify_init(),inotify_add_watch(),inotify_rm_watch()调用和read()调用,以在测试中需要时返回错误.

但是问题是我找不到模拟inotify失败的方法.我想知道是否有人已经遇到这样的问题并且知道一些解决方案.

解决方法:

如果您想避免任何嘲笑,您最好的选择就是直接达到操作系统限制,从而引发错误.例如,如果调用进程已达到打开文件描述符数量的限制,则inotify_init可能因EMFILE errno而失败.为了达到100%的精度,您可以使用以下两个技巧:

>通过changing values in procfs动态控制运行进程的限制
>将您的应用程序进程分配给专用的cgroup,并通过cgroups API为其提供〜0%的CPU时间来“挂起”它(这是Android调节后台应用程序并实现其节能的“打ze”模式的方式).

inotify的所有可能错误条件都记录在inotify,inotify_init和inotify_add_watch的手册页中(我不认为inotify_rm_watch可能会失败,除非纯粹是代码中的编程错误).

除了普通的错误(例如,遍历/ proc / sys / fs / inotify / max_user_watches)外,inotify还具有几种故障模式(队列空间耗尽,手表ID重用),但是从严格的意义上讲,这些不是“故障”.

当有人执行文件系统更改的速度快于您的反应速度时,就会发生队列耗尽.重现很容易:使用cgroups在打开inotify描述符时暂停程序(这样就不会耗尽事件队列),并通过修改观察到的文件/目录快速生成大量通知.一旦您具有未处理事件的/ proc / sys / fs / inotify / max_queued_events,并且取消暂停程序,它将收到IN_Q_OVERFLOW(并且可能会错过一些无法放入队列的事件).

监视ID重用非常繁琐,因为现代内核从监视ID的文件描述符行为转换为PID行为.您应该使用与测试PID重用时相同的方法-创建并销毁许多inotify监视,直到整数监视ID结束为止.

Inotify也有一些棘手的极端情况,在正常操作期间很少发生(例如,我知道的所有Java绑定,包括Android和OpenJDK,都无法正确处理所有它们):相同inode问题和处理IN_UNMOUNT.

在inotify文档中很好地解释了相同inode的问题:

A successful call to inotify_add_watch() returns a unique watch descriptor for this inotify instance, for the filesystem object (inode) that corresponds to pathname. If the filesystem object was not previously being watched by this inotify instance, then the watch descriptor is newly allocated. If the filesystem object was already being watched (perhaps via a different link to the same object), then the descriptor for the existing watch is returned.

用简单的话来说:如果您观看两个硬链接到同一文件,则它们的数字监视ID将相同.如果您将手表存储在诸如哈希表之类的表中,并用整数手表ID作为键,则此行为很容易导致无法跟踪第二个inotify手表.

第二个问题更难观察,因此即使不是错误模式,也很少得到适当的支持:卸载分区,当前可通过inotify进行观察.棘手的部分是:Linux文件系统在您打开文件描述符时不允许您自行卸载,但是通过inotify观察文件不会阻止文件系统的卸载.如果您的应用观察到单独文件系统上的文件,并且用户卸载了该文件系统,则必须准备处理所产生的IN_UNMOUNT事件.

以上所有测试都应该可以在tmpfs文件系统上执行.

上一篇:二、Linux实时同步软件之inotify


下一篇:Centos 配置rsync远程同步及使用inotify+rsync实时备份