【问题标题】:How Linux handles the case when multiple processes try to replace the same file at the same time?Linux 如何处理多个进程同时尝试替换同一个文件的情况?
【发布时间】:2019-06-07 05:42:55
【问题描述】:

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

提前致谢。

【问题讨论】:

  • 线程还是进程?
  • 您需要提供更多详细信息,例如用于打开文件的模式。您还应该解释 "replace 的含义。您是在换入一个新文件,例如 mv new.txt old.txt?还是在做其他事情,例如将新内容写入现有文件而不增加尺寸?
  • @jww 每个线程都想在有更新时替换文件。所以我猜模式应该是写模式。
  • "mv new.txt old.txt",这就是我要做的……

标签: c++ linux concurrency


【解决方案1】:

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

filename --> inode --> data

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

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

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

【讨论】:

  • 感谢杰里米的回答。如果是进程而不是线程,行为会如何?
  • 就这个问题而言,我认为进程和线程之间的行为没有任何显着差异。
  • @user1228352 - 回答者是正确的,在这种情况下,进程和线程之间的行为实际上没有区别。在 Linux 中,线程只是进程的一种特殊情况。
【解决方案2】:

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

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

还有一些细节,比如“如果有人删除了我打开的文件会怎样?”另一个答案解释得很好。

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

因此,对于您的非常笼统和开放式问题的答案必须是模糊、抽象和手摇的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2011-05-01
    • 2020-06-30
    • 1970-01-01
    • 2015-01-29
    相关资源
    最近更新 更多