标准要求重命名是原子的吗?

And*_*nle 5 c language-lawyer

我试图回答这个问题时出现了一个有趣的问题:

我的fs上有mv原子吗?

rename()功能是否需要标准的原子功能?

州的POSIX标准rename的"基本原理"部分:

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

但是,最新公开的ISO C标准部分rename完整地指出:

7.21.4.2 rename功能

概要

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

描述

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

返回

rename如果操作成功,则该函数返回零,如果失败则返回非零值,在这种情况下,如果该文件先前存在,则其原始名称仍然是已知的.

rename()在ISO C标准的部分中没有明确要求任何类型的原子性.

编写了许多程序,这些程序依赖于显然特定于实现的原子性rename(),我认为原子性是一个要求,并且对C标准的缺乏感到惊讶.

但POSIX标准表明ISO C标准要求rename()是原子的.

解释(S)?

Jon*_*ler 5

您对 POSIX 标准的引用来自rename()(非规范性)“基本原理”部分。主要条目——实际的规范材料——开始:

对于重命名():[CX] [选项开始] 此参考页面上描述的功能符合 ISO C 标准。此处描述的要求与 ISO C 标准之间的任何冲突都是无意的。本 POSIX.1-2008 卷遵循 ISO C 标准。[选项结束]

rename()函数将更改文件的名称。该old参数指向的文件路径名进行重命名。该new参数指向文件的新路径。[CX] [选项开始] 如果new参数不能解析为目录类型文件的现有目录条目,并且new参数包含至少一个非<slash>字符并在处理完<slash>所有符号链接后以一个或多个尾随字符结尾,则将rename()失败。

[选项结束]

条目的所有其余部分都在[CX](C Extension) 标签内,并讨论了其他特殊行为。

你引用的理由说:

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

最后一句中提到的“该规范”是扩展定义,包括对目录操作的规范和“当新参数命名已存在的文件时”,而不是 C 标准中的规范,正如您所观察到的, 没有说任何关于原子性的事情(非常合理;有些系统可以支持 Crename()而不能支持 POSIX 更严格的原子性要求)。

我看到这正是TC在他们的评论中提出的论点——我同意 TC

  • 谢谢你。所以答案是“不,`rename()` 不需要是原子的。” 这是有道理的 - 但我问这个问题是因为我一直*假设*`rename`必须是原子的,当我找不到时感到很惊讶。而且总是很难证明是否定的。 (2认同)