如何使用 readdir/inotify 避免这种竞争条件?

How do I avoid this race condition with readdir/inotify?

提问人:William Pursell 提问时间:8/23/2011 最后编辑:Marco BonelliWilliam Pursell 更新时间:8/20/2023 访问量:2065

问:

假设我想对目录中的所有文件调用某个命令,并设置监视以对该目录中创建的所有文件调用该命令。如果我这样做:

while( ( sdi = readdir( d )) != NULL ) { ... }
closedir( d );
/* Files created here will be missed */
inotify_add_watch( ... );

那么一些文件可能会被遗漏。如果我在 之前调用,文件可能会作两次(这需要相当多的基础设施来防止两次操作,而且似乎边缘情况很难处理)。有没有一种简单的方法可以避免记录循环期间处理的所有文件的名称,并将其与结构中返回的名称进行比较?我可以 尽量减少与以下人员的必要比较:inotify_add_watch()readdir()readdirinotify_event

while( ( sdi = readdir( d )) != NULL ) { ... }
inotify_add_watch( ... );
while( ( sdi = readdir( d )) != NULL ) { /* record name */ ... }
closedir( d );

通常第二个循环什么也做不了,但这感觉像是一个糟糕的黑客。readdir()

Linux inotify readdir

评论

0赞 William Pursell 10/25/2019
我实际上不记得问过这个问题,而且有了几年的经验,我现在会回答这个问题,你甚至不应该试图避免比赛条件。确保你在循环中所做的任何事情都是幂等的,这样你就不在乎你是否多次执行这些操作。

答:

3赞 Michał Górny 8/23/2011 #1

你根本做不到。你破解的越多,你得到的竞争条件就越多。

最简单的实际工作解决方案是在使用 之前设置监视,并保留已使用的名称(或其哈希值)的列表(集)。opendir()

但这也不完美。用户可以在文本编辑器中打开文件;你修复它,用户保存它,目录仍然包含未修复的文件,尽管它在你的列表中。

最好的方法是能够让程序通过其内容实际区分使用过的文件。换句话说,你设置了watch,在结果上调用命令,然后在inotify results上调用它,并让命令本身知道文件是否已经正常。readdir()