我的FS上的MV是原子的吗?


Answers:


9

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

要明确,mv指定

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

重命名功能规范状态:

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

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

7.21.4.2 rename功能

概要

#include <stdio.h>
int rename(const char *old, const char *new);

描述

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

退货

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

令人惊讶地,请注意,原子性没有明确的要求。最新的公共C标准可能在其他地方要求它,但是我找不到它。如果有人可以找到这样的要求,那么欢迎您进行编辑和评论。

另请参见rename()是原子的吗?

根据Linux手册页

如果newpath已经存在,它将被原子替换,这样就不会再有其他尝试访问的进程 newpath发现它丢失了。但是,可能会有一个窗口,其中oldpath和都newpath指向要重命名的文件。

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

但是,如果这需要走多远,那么测试验证原子性可能会非常困难。您不清楚“如何检查mv是否为原子”的含义。您是否需要原子性的要求/规范/文档,还是需要进行实际测试

另请注意,以上假设两个操作数文件名位于同一文件系统中。我发现该mv实用程序没有标准限制可以执行该操作。


我必须确保这一举动是原子的。测试足够接受这一点吗?我不知道 是的,我正在使用相同的fs(ext4至ext4)。
Tizianoreica '16

1
POSIX也不保证原子性,但是Linux与大多数unix变体一样,保证ext4等“本机”文件系统。
吉尔斯(Gillles)“所以-别再邪恶了”

1
鉴于ISO C仅定义了一个程序的行为,而没有定义整个系统的行为,因此它对rename原子性一无所知是很奇怪的。
吉尔(Gilles)'“ SO-别再作恶了”

3
我阅读了“该规范”,指的是前一句话(“其中包含...指定了新参数命名一个已经存在的文件时的行为”),它引用了POSIX文档的较早部分(“一个名为new的链接应为始终在其他线程中可见...,并引用新旧文件所引用的文件...“)。换句话说,POSIX承诺实施ISO C标准,并提供ISO C所不能提供的其他保证。这种解释有帮助吗?
SimonJ

1
@Tizianoreica我知道这是一篇古老的文章,但是我刚刚看到了您的评论,并认为我应该澄清一下:实际的文件系统必须相同,重命名才能是原子的。不仅是同一类型的文件系统。例如,如果您有/一个ext4 fs和/tmp一个不同的ext4 fs,则您不能从一个原子原子到另一个原子原子mv。
沃丁


-1

除了检查系统调用及其原子性之外,也许inotify-tools可以作为测试,尽管我不确定这是否可以保证原子性。

打开2个炮弹。观看其中之一的移动目标目录:

inotifywait -m target/

将文件移到另一个目录中:

mv foobar target/

inotifywait应只显示一行:

target/ MOVED_TO foobar

它相比于响应于似乎原子ls target/touch target/a,从而产生像多行消息:

# the response to ls target/
target/ OPEN,ISDIR 
target/ ACCESS,ISDIR 
target/ CLOSE_NOWRITE,CLOSE,ISDIR 

聚苯乙烯

我认为,至少它表明文件的异步多进程合作是安全的inotify(实际上是原子的):无论如何,只有在inotify操作后给出最终信号后,您才响应。例如,可以使用轻松,安全地实施生产者-消费者设置inotify

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.