为啥 Python 文件锁库会删除 Windows 上的锁文件,而不是 UNIX?

Posted

技术标签:

【中文标题】为啥 Python 文件锁库会删除 Windows 上的锁文件,而不是 UNIX?【英文标题】:Why does the Python filelock library delete lockfiles on Windows but not UNIX?为什么 Python 文件锁库会删除 Windows 上的锁文件,而不是 UNIX? 【发布时间】:2020-01-25 15:50:41 【问题描述】:

我正在使用the filelock module for Python。

在 Windows 上,当一个锁被释放时,支持它的文件被删除。

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

这是否有原因在操作系统之间有所不同?如果没有理由不同,这些行为中哪一个更正确?

【问题讨论】:

我已将其编辑为更清晰、更具体的问题;希望它会重新开放。 (如果/何时发生这种情况,请随时@-通知我,我会在上面的 cmets 中用内容的扩展版本写一个答案)。 @CharlesDuffy:这个问题现在是开放的。 @user000001,谢谢;我添加了一个答案,将现在删除的 cmets 的详细信息与先前引用的评论线程的内容进行了扩展。 @CharlesDuffy,这个问题is being discussed on Meta。 【参考方案1】:

专门针对py-filelock

filelock用于删除 UNIX 上的锁定文件;自 benediktschmitt/py-filelock#31 起,此行为已被删除,它指的是 flock(): 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 关闭其对文件的句柄,从而释放其锁定。 inode 没有被删除,因为 Program 2 仍然持有一个句柄。 程序 2 被授予它在删除发生之前打开的文件句柄(在现已取消链接的文件 A1 上)一直在等待的锁,并且能够继续执行。 程序 3 创建并打开一个名为“A”的新文件 A2(具有一个新的且不同的 inode)(因为 A1 的 inode 不再链接到该名称,所以该文件可用),并获得一个文件句柄。 程序 3 请求锁定它拥有的文件句柄。 这是立即授予的,因为 A2 与 A1 是不同的文件,并且仍在运行的程序 2 持有 A1 的锁定,而不是 A2。因此,我们最终得到了两个程序——程序 2 和程序 3——认为它们持有相同的锁。

因此,以上说明了在 UNIX 上,删除锁文件如何允许出现竞争条件,其中一个锁似乎同时被两个程序持有。

【讨论】:

以上是关于为啥 Python 文件锁库会删除 Windows 上的锁文件,而不是 UNIX?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 Asp.Net Core 中使用 Steeltoe.Discovery.Client 库会不断增加内存?

为啥 AWS Lambda 环境中的 EPPlus Excel 库会引发“'Gdip' 的类型初始化程序引发异常”

dup文件锁库函数函数调用(day07)

为啥KEIL5.15用默认库会出4个错误

删除github中的原始存储库时导入的存储库会发生啥

为啥 Python 会找到与 Windows 不同的文件大小?