我的 fs 上的 mv 是原子的吗?

Tiz*_*ica 16 posix move mv

如何检查mv我的 fs (ext4)是否是原子的?

操作系统是 Red Hat Enterprise Linux Server 6.8 版。

一般来说,我该如何检查?我环顾四周,没有发现我的操作系统是否是标准的 POSIX。

And*_*nle 11

有趣的是,似乎答案可能是“这取决于”。

明确地说,mv被指定

mv实用程序将执行相当于行动rename() 功能

重命名功能规范状态:

rename()对于常规文件,此函数等效于 ISO C 标准定义的函数。它在此处的包含扩展了该定义以包括对目录的操作并指定当新参数命名已存在的文件时的行为。该规范要求函数的动作是原子的。

但最新的ISO C规格rename()状态:

7.21.4.2rename功能

概要

#include <stdio.h>
int rename(const char *old, const char *new);
Run Code Online (Sandbox Code Playgroud)

描述

rename函数使名称为 指向的字符串的文件old从此被 指向的字符串指定的名称所知晓new。命名的文件old不再可以通过该名称访问。如果new在调用rename函数之前存在由 指向的字符串命名的文件,则行为是实现定义的。

退货

rename如果操作成功,则该函数返回零,如果操作失败,则返回非零,在这种情况下,如果文件先前存在,它仍然可以通过其原始名称知道。

令人惊讶的是,请注意对原子性没有明确的要求。在最新的公开可用的 C 标准中的其他地方可能需要它,但我找不到它。如果有人能找到这样的要求,非常欢迎编辑和评论。

另见rename() 是原子的吗?

根据Linux 手册页

如果newpath已经存在,它将被原子地替换,因此在尝试访问的另一个进程 newpath不会发现它丢失的时候。但是,可能会出现一个窗口,其中oldpath和 都newpath指向被重命名的文件。

Linux 手册页声称文件的替换将是原子的。

测试验证原子性可能非常困难,如果这是你需要走多远的话。你不清楚你在使用“我如何检查 mv 是否是原子的”时的意思。你想要它是原子的需求/规范/文档,还是你需要实际测试它?

还要注意,上面假设两个操作数文件名在同一个文件系统中。我找不到mv强制执行该实用程序的标准限制。

  • 我读“那个规范”是指上一句(“它在这里包含......指定当新参数命名一个已经存在的文件时的行为”),它指的是POSIX文档的早期部分(“一个名为new的链接应该在整个过程中保持对其他线程可见......并参考新的或旧的文件......”)。换句话说,POSIX 承诺实施 ISO C 标准,并提供超出 ISO C 提供的额外保证。这种解释有帮助吗? (3认同)
  • POSIX 也不保证原子性,但 Linux 与大多数 UNIX 变体一样,对于“本机”文件系统(例如 ext4)可以保证原子性。 (2认同)
  • @Tizianoreica 我知道这是一篇古老的帖子,但我刚刚看到您的评论,并认为我应该澄清一下:实际文件系统必须相同才能使重命名成为原子。不仅仅是相同的*类型*的文件系统。例如,如果你有 `/` 作为一个 ext4 fs 和 `/tmp` 作为一个不同的 ext4 fs 那么你*不能*从一个到另一个原子地 mv。 (2认同)