为什么Python的文件锁库在Windows上会删除锁定文件,而在UNIX上不会?

8
我正在使用Python的filelock模块。
  • 在Windows上,当锁被释放时,支持它的文件会被删除。

  • 在UNIX上,即使锁被释放,锁文件仍然存在于文件系统中。

这两个操作系统之间为什么会有这种不同呢?如果没有必要区分,那么哪种行为更正确?

我已经将这个问题编辑成更清晰和具体的形式,希望它能够重新开放。如果/当这种情况发生时,请随时@-通知我,我会用我的评论中的扩展版本编写答案。 - Charles Duffy
@CharlesDuffy:该问题目前是开放的。 - user000001
@user000001,谢谢;我已经添加了一个答案,将现在已删除的评论中的细节与先前引用的评论线程内容进行了合并和扩展。 - Charles Duffy
1
@CharlesDuffy,这个问题正在Meta上讨论。 - Makoto
1个回答

8

关于py-filelock的具体说明

filelock库曾在UNIX系统上删除锁文件;但随着benediktschmitt/py-filelock#31flock(): removing locked file without race condition?的出现,这种行为已被移除。后者讨论了本回答中后面部分描述的相同竞争条件。


通用实践的差异原因

由于操作系统语义不同,因此在每种情况下都需要采用不同的方法。在UNIX中,即使有句柄打开,也可以删除文件,因此不应删除锁文件,否则两个程序都可能认为自己持有相同的锁,当实际上他们持有完全不同的inode,在不同的时间点下被引用为同一文件名下的内容。

相比之下,Windows上默认的文件系统语义使得在任何程序打开文件时都无法删除该文件(尽管NTFS足够强大以支持这样做,但它被人为地阻止以向后兼容到围绕FAT限制设计的程序),因此在Windows上删除锁文件是安全的:如果删除成功,那就证明没有人持有该锁(甚至没有在打开文件以后获取该锁的过程中)。


一个具体的竞争条件示例

为了举例说明UNIX允许打开的文件被取消链接如何使得删除锁文件变得危险,考虑以下常见竞争条件的示例:

  • 程序1创建并打开文件A1(名称为“A”),接收到新创建的文件的inode(实际文件本身所反映的对象,而不是它所附加的目录条目)附加的文件句柄。
  • 程序1请求对该句柄进行排他性咨询锁定。没有其他进程拥有相同文件的句柄,因此其锁定请求被授予。
  • 程序2打开文件A1,同时获得了第二个文件句柄。
  • 程序2请求对该句柄进行排他性咨询锁定。但是,由于程序A已经持有锁,请求被阻塞--也就是说,程序在等待操作系统稍后将控制权传递回它时可以授予锁定。
  • 程序1完成了需要锁定的进程。
  • 程序1使用unlink()系统调用删除锁定文件。(在UNIX上为了安全起见,可以省略此步骤)。这不会删除文件本身(“inode”),直到没有任何程序打开它,但它确实立即从先前包含它的目录中删除了指向该文件的链接。
  • 程序1关闭其对文件的句柄,从而释放其锁定。由于程序2仍然持有一个句柄,因此不会删除inode。
  • 程序2被授予了在之前进行删除操作之前打开的文件句柄(在现在未链接的文件A1上)上等待的锁定,并能够继续执行。
  • 程序3创建并打开一个新文件A2(具有新和不同的inode),名称为“A”(因为A1的inode不再链接到该名称),同时获得了文件句柄。
  • 程序3请求其所拥有的文件句柄上的锁定。这立即被授予,因为A2是与A1不同的文件,并且仍在运行的程序2持有A1的锁定,而不是A2。因此,最终会出现两个程序--程序2和程序3--认为它们持有相同的锁定。

因此,以上说明了如何在UNIX上通过删除锁文件允许竞态条件,在这种情况下,锁可能看起来被两个程序同时持有。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接