8

这篇文章指出,

fd = os.open('foo.lock', os.O_CREAT|os.O_EXCL|os.O_RDWR)

“在大多数文件系统上都是原子的”。这是真的(在 Unix 和 Windows 上)吗?在哪些文件系统上?

文档声明提到的标志在 Unix 和 Windows 上可用,因此它看起来像是一种用于文件锁定的诱人的跨平台方法(标志O_CREATO_EXCL确保调用进程创建文件)。

4

1 回答 1

6

对于符合 UN*X(根据 OpenGroup 认证的 POSIX / IEEE 1003.1)系统,该行为被保证为 OpenGroups 规范强制执行此操作。引用:open(2)

O_EXCL
如果设置了 O_CREAT 和 O_EXCL,如果文件存在,则 open() 将失败。检查文件是否存在以及如果文件不存在则创建文件对于执行 open() 的其他线程在同一目录中命名相同文件名并设置了 O_EXCL 和 O_CREAT应该是原子的。如果设置了 O_EXCL 和 O_CREAT,并且路径名称为符号链接,则无论符号链接的内容如何,​​open() 都将失败并将 errno 设置为 [EEXIST]。如果设置了 O_EXCL 而未设置 O_CREAT,则结果未定义。

“常见的”UN*X 和类似 UN*X 的系统(Linux、MacOSX、*BSD、Solaris、AIX、HP/UX)的行为肯定是这样的。

由于 Windows API 没有open()这样的功能,因此必须根据本机 API 重新实现库函数,但可以保持语义。

我不知道哪些广泛使用的系统符合要求。QNX 虽然未经 POSIX 认证,但在其open(). *BSD 手册页没有明确提到“原子性”,但 Free/Net/OpenBSD 实现了它。甚至像 SymbianOS 这样的外来系统(像 Windows 一样没有 UN*Xopen系统调用)也可以进行原子打开/创建。

要获得更有趣的结果,请尝试找到一个操作系统/C 运行时库,它具有但未open()实现上述语义......并且 Python 将在其上运行线程(让你到那里,MSDOS......)。

编辑:我的帖子特别关注“哪些操作系统具有此特性open?” - 答案是“几乎所有人”。写。但是对于文件系统,情况有所不同,因为网络文件系统- 无论是 NFS、SMB/CIFS 还是其他文件系统,并不总是保持不变O_EXCL,因为这可能导致拒绝服务(如果客户端执行open(..., O_EXCL, ...)然后停止与文件服务器通信 /已关闭,其他所有人都将被锁定)。

于 2013-02-25T17:04:59.677 回答