是否有一种非特定于平台的方法来执行原子操作“如果 File2 不存在,则将 File1 重命名为 File2,否则给出错误”?我知道我可以检查 File2 是否存在,如果不存在则重命名该文件,但是当其他进程在检查和 rename() 之间创建 File2 时,这会引入潜在的竞争条件。
在 Linux 下,有一个 renameat2()
函数,它通过设置 RENAME_NOREPLACE
标志来完成此操作。不幸的是,联机帮助页上写着
renameat2() is Linux-specific.
我什至不知道是否所有 libc 实现都支持此调用,还是仅 glibc。
对于我的用例,在同一目录内重命名就足够了,我不需要支持移动到完全不同的路径。
这可能与https://stackoverflow.com/a/230581/5562035相关和 Atomically swap contents of two files on Linux
最佳答案
Is there a non-platform-specific way of doing an atomic "rename File1 to File2 if File2 does not exist, otherwise give an error"?
C标准库仅提供rename()
用于更改文件名,标准对该函数是这样说的:“如果在调用 rename
函数之前存在由 new
指向的字符串命名的文件,该行为是实现定义的。”因此,如果“非平台特定”被解释为“由 C 标准指定”,那么不,不存在这样的机制。
但是,如果我们扩展“非特定于平台”的范围以允许 POSIX 指定的设施,那么您可以依赖 link()
,其中
shall atomically create a new link for the existing file and the link count of the file shall be incremented by one. [and] shall fail if [... the second argument] resolves to an existing directory entry or refers to a symbolic link.
因此,您可以首先创建到该文件的新(硬)链接,如果指定的路径名指定现有文件或符号链接(symbolic link),则失败,然后在成功后删除原始链接。
您可能感兴趣的最著名的非 POSIX 平台是 Windows。我不确定是否有任何方法可以在 Windows 上完成您所要求的操作,但如果有,您可以考虑编写一个包装函数,该函数使用条件编译来选择 POSIX 或 Windows 实现。
关于C 跨平台 renameat2() rename-if-not-exists 功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41536199/