重命名()原子?

时间:2011-08-14 03:38:27

标签: linux file-rename atomicity vfs

我无法通过实验检查这一点,也无法从手册页中收集它。

假设我有两个进程,一个从directory1移动(重命名)file1到directory2。假设另一个并发运行的进程将directory1和directory2的内容复制到另一个位置。复制是否有可能使directory1和directory2都显示file1 - 即在移动之前复制directory1,在第一个进程移动之后复制directory2。

基本上rename()是原子系统调用吗?

由于

4 个答案:

答案 0 :(得分:24)

是和否。

假设操作系统没有崩溃,

rename()是原子的。它不能被任何其他文件系统op。

拆分

如果系统崩溃,您可能会看到ln()操作。

另请注意,在网络文件系统上运行时,如果操作成功,您可能会获得ENOENT。本地文件系统无法做到这一点。

答案 1 :(得分:23)

这是一个非常晚的答案,但是......是rename()是原子的,但不是你的问题。在Linux下,rename(2)说:

  

然而,当覆盖时,可能会有一个窗口,其中既有旧路径   和newpath指的是正在重命名的文件。

但是rename()在一个非常重要的意义上仍然是原子的:如果你用它来覆盖一个文件,那么你最终将使用旧版本或新版本而不是其他内容。

[更新:,但正如@ jonas-wielicki在评论中指出的那样,您需要使用fsync()确保您重命名的文件实际上具有最新内容和朋友们。]

  

如果newpath已经存在,它将被原子替换(受制于   一些条件;见下面的错误),所以没有任何意义   尝试访问newpath的另一个进程会发现它丢失。

如果你看到ERRORS,你会发现重命名可能会失败,但它永远不会破坏原子性。

这完全来自Linux手册页。我不知道的是,如果您在网络文件系统上执行rename(),其中服务器运行不同的操作系统。客户是否希望保证原子性呢?我对此表示怀疑。

答案 2 :(得分:6)

我不确定你问题的“基本”部分是否有效。除非你们之间有某种同步,否则原子重命名的方式并不重要。如果目录副本在重命名之前到达那里,那么你将在两个地方都拥有file1。

我不确定你是否意味着线程或进程,但如果两者都有锁定机制,则线程锁是最简单的,因为它们不必跨越进程边界。

答案 3 :(得分:0)

gnu libc manual

  

重命名的一个有用的功能是,新名称的含义从原子上从以前存在的任何文件“原子地”更改为它的新含义(即称为旧名称的文件)。在旧含义和新含义之间没有“新名称”不存在的瞬间。如果操作过程中发生系统崩溃,则两个名称可能仍然存在;但是newname只要存在就永远是完整的。

相关问题