os.open()在哪些系统/文件系统中是原子的?
1 个回答
对于符合UN*X标准的系统(也就是经过POSIX / IEEE 1003.1认证的系统),它们的行为是有保障的,因为OpenGroup的规范对open(2)
有明确的要求。引用如下:
O_EXCL
如果同时设置了O_CREAT和O_EXCL,那么如果文件已经存在,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*X风格的open
系统调用)也能做到原子打开/创建。
如果想要更有趣的结果,可以试着找一个有open()
但不实现上述语义的操作系统或C运行时库……并且Python可以在上面运行并使用线程(这就把MSDOS给抓住了……)。
编辑:我的帖子特别关注“哪些操作系统具有open
的这个特性?”——答案是“几乎所有的系统都有”。不过关于文件系统,情况就不同了,因为网络文件系统——无论是NFS、SMB/CIFS还是其他,通常不总是维护O_EXCL
,因为这可能导致拒绝服务(如果一个客户端执行open(..., O_EXCL, ...)
然后停止与文件服务器通信或被关闭,其他人就会被锁定)。