是rename()的原子



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

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

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

谢谢

是和不是。

rename()是原子的,假设操作系统没有崩溃。它不能被任何其他文件系统分割。

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

还请注意,在操作网络文件系统时,当操作成功时可能会获得ENOENT。本地文件系统不能这样对您。

这是一个很晚的回答,但是…是的,rename()是原子的,但不是你问题的意义。在Linux下,rename(2)显示:

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

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

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

如果newpath已经存在,它将被自动替换(根据几个条件;(见下面的错误),所以没有点另一个试图访问newpath的进程会发现它丢失了。

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

这些都来自Linux手册页。我不知道的是,如果您在服务器运行不同操作系统的网络文件系统上执行rename()操作。那么客户端还有希望保证原子性吗?我很怀疑。

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

我不确定你指的是线程还是进程,但如果两者都有锁机制,线程锁是迄今为止最简单的,因为它们不必跨越进程边界。

gnu libc手册说

rename的一个有用的特性是newname的含义会"自动地"从任何先前存在的同名文件更改为它的新含义(即,称为oldname的文件)。在新旧意思之间,没有一个时刻是不存在的。如果在操作过程中出现系统崩溃,两个名称可能仍然存在;但是如果newname存在的话,它将始终是完整的。

相关内容

  • 没有找到相关文章

最新更新