【问题标题】:How does linux manage concurrent file writing and renaming?linux如何管理并发文件写入和重命名?
【发布时间】:2020-11-22 23:36:48
【问题描述】:

我有两个 C++ 程序,一个写入文件,另一个重命名它(锁定它,但让第一个也能够写入)并处理它。我的问题是,这可能吗?在一个场景中,当第一个正在写入时,第二个尝试重命名同一个文件,会发生什么?我需要一个坚如磐石的解决方案,涵盖所有角落案例。对于这个小任务,小型数据库似乎太复杂了。我需要坚持,因为第二个程序可能运行不成功,必须重试。

【问题讨论】:

  • 重命名文件是原子的(如果在同一个文件系统中)。
  • “我需要一个坚如磐石的解决方案,涵盖所有角落案例” - 我认为您无法在您提供的限制范围内获得一个。
  • 目录条目不是文件。您使用名称来访问文件,但一旦“打开”完成,用于访问文件的名称就完全无关紧要了。

标签: c++ linux file io


【解决方案1】:

Linux 中的文件锁定很混乱。有几种不同的技术,但它们都是建议锁,这意味着其他进程可以通过不检查锁来忽略锁。 如果另一个进程不检查锁,您无法阻止该进程写入文件。

我会指出flock() 的存在,但这仍然只是建议性的,不适用于远程文件系统。


问题是在 Linux 中存在三个独立的概念:

  • 文件数据 - “磁盘上”的实际数据。
  • 文件名 - 这些只是目录结构中的句柄,提供打开文件的访问权限。
  • 文件描述符/文件描述 - 打开文件后,进程自己对文件数据的引用。

两个进程可以在同一个文件上有一个文件描述(同时打开)。如果文件被重命名,它只会影响将来对open() 的调用;重命名甚至删除文件只会删除旧文件名。实际上一个打开的文件可以被删除,数据会一直保留在磁盘上,直到打开的文件描述被关闭。


如果您可以控制所有写入文件的程序,那么锁定文件的一种常用方法是使用both O_CREAT and O_EXCL 创建一个锁定文件。即:锁定my_file.txt 你创建一个.my_file.txt.lock。如果锁定文件已经存在,这将失败。但这仍然需要另一个进程先检查。

这通常被认为是最有效的锁定类型。


您首先重命名的解决方案不会好很多。如果另一个进程在你重命名文件之前打开了文件,那么另一个进程将继续写入文件并且永远不会知道有什么不同。

【讨论】:

    【解决方案2】:

    来自rename,我的粗体:

    rename() 重命名文件,如果需要,在目录之间移动它。 文件的任何其他硬链接(使用链接(2)创建)是
    不受影响。 oldpath 的打开文件描述符不受影响

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-13
      • 1970-01-01
      • 2010-09-14
      • 1970-01-01
      • 1970-01-01
      • 2015-01-29
      • 1970-01-01
      相关资源
      最近更新 更多