当多个进程尝试同时替换同一文件时,Linux 如何处理这种情况?
How Linux handles the case when multiple processes try to replace the same file at the same time?
我知道这是一个理论问题,但还没有得到任何令人满意的答案。所以想把这个问题放在这里。 我有多个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,并以奇怪和神秘的方式相互交互。
因此,对你非常笼统和开放式问题的回答必然是模糊的、抽象的和挥手的。
- 警告处理为错误这里有什么问题
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用流处理接收到的数据
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 基于多个条件处理地图中的所有元素
- 如何用数字处理log(0)
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- 错误处理.将系统错误代码映射到泛型
- 从文本文件中读取时钟时间和事件时间并进行处理
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 用于矢量处理的多个线程
- 处理未处理的异常更改C++
- 使用信号处理程序处理从 FIFO 接收的数据
- 使用QT的C 处理DOM处理后的XML属性顺序
- C++异常处理如何处理异常派生类
- 如何处理信号处理库的输入/输出类型