当多个进程尝试同时替换同一文件时,Linux 如何处理这种情况?

How Linux handles the case when multiple processes try to replace the same file at the same time?

本文关键字:处理 何处理 情况 进程 替换 文件 Linux      更新时间:2023-10-16

我知道这是一个理论问题,但还没有得到任何令人满意的答案。所以想把这个问题放在这里。 我有多个C++进程(也想知道线程行为),它们争辩同时替换同一个文件。在 Linux 中做多少安全的事情(使用 Ubuntu 14.04 和 Centos 7)?我需要放锁吗?

提前谢谢。

基于 Unix 的操作系统(如 Linux)的文件系统是围绕 inode 的概念设计的,inode 是描述有关文件的各种元数据的内部记录。 通常,用户或程序不会直接与它们交互,但是它们的存在使这些文件系统具有间接性,允许它们提供其他操作系统(阅读:Windows)无法提供的一些有用的语义。

filename --> inode --> data

特别是,当文件被删除时,实际发生的是文件的索引节点与其文件名的分离;而不是(必然)删除文件的数据本身。 也就是说,文件及其内容可以继续存在(尽管从用户的角度来看是不可见的),直到所有进程都关闭了在该文件上打开的文件句柄;一旦任何进程都不再访问 inode,只有这样,文件系统才会真正将文件的数据块标记为可用且可供重用。 同时,文件名可用于与另一个文件的索引节点(和数据)相关联,即使旧文件的索引节点/数据在技术上仍然存在。

这样做的结果是,在Linux下,随时删除(或重命名)文件是完全有效的,即使其他线程/进程正在使用它;你的删除将成功,任何其他程序在那个时刻打开该文件都可以继续读取/写入/使用它,就像它没有被删除一样。 唯一不同的是文件名将不再出现在其目录中,当他们对文件调用fclose()(或close()等)时,文件的数据将消失。

由于执行mv new.txt old.txt与执行rm old.txt ; mv new.txt old.txt基本相同,因此在没有任何同步的情况下从多个线程执行此操作应该没有问题。 (请注意,多个线程或进程同时打开同一文件并同时写入文件的情况略有不同,这有点危险;什么都不会崩溃,但如果他们不小心,它们很容易覆盖彼此的数据并损坏文件)

这在很大程度上取决于您要做什么以及如何使用这些文件。一般来说,在像Linux这样的Unix/Posix系统中,如果多个进程进行所有文件调用,所有文件调用都将成功,操作系统处理争用的一般方式是"最后一个做某事的人获胜"。本质上,对文件系统的所有修改都是序列化的,因此文件系统始终处于一致状态。但除此之外,这是一场混战。

不过这里有很多细节。在打开像O_EXCL这样的文件时使用标志,如果另一个进程先这样做(一种锁定),可能会导致失败。有建议(也就是,没有人作系统强迫注意它们)锁定系统,如文件内容的flock(尝试键入man 2 flock以了解更多信息)。还有更多特定于Linux的强制锁定系统。

还有一些细节,如"如果有人删除了我打开的文件会发生什么?"另一个答案解释正确和很好。

最后,关于是否保证对文件系统的任何特定更改都被永久记录,或者如果有人轻弹电源开关,它是否有可能消失,这有很多细节。一旦你真正深入研究它,那就是一团糟,在对操作系统撒谎的狡猾硬件到涵盖此问题不同方面的不同 Linux 系统调用的混乱泥沼之间,通常从 Unix/Posix 历史的不同时代进入 Linux,并以奇怪和神秘的方式相互交互。

因此,对你非常笼统和开放式问题的回答必然是模糊的、抽象的和挥手的。