【问题标题】:Is a file guaranteed to be openable for reading immidiately after ofstream::close() has returned?在 ofstream::close() 返回后,是否保证可以立即打开文件以供读取?
【发布时间】:2013-03-26 14:39:16
【问题描述】:

我需要我的代码(C++,在 linux 上)调用第二个可执行文件,之前编写了一个输出文件,该文件可以被第二个程序读取。是否天真的方法,

std::ofstream out("myfile.txt");
// write output here
out.close();
system("secondprogram myfile.txt");

遇到潜在的竞争条件,即使 out.close() 已执行,secondprogram 也无法立即读取该文件?如果是这样,解决此问题的最佳做法是什么?

三个注意事项:

  • 如果这取决于文件系统,我对 ext3 和 tmpfs 上的行为感兴趣。
  • 显然还有其他原因(文件权限等)导致第二个程序可能无法打开文件;我只是对竞争条件的可能性感兴趣。
  • 上例中的硬编码文件名是为了简单起见;实际上我使用mkstemp

【问题讨论】:

  • 是的,这是有保证的。你确定问题是关于那个的吗?你strace你的程序了吗?
  • @BasileStarynkevitch 我(还)没有遇到问题:我只是想检查一下我不会有一个未来。您能否详细说明是 C++、Linux、文件系统还是其他东西在做出这种保证?
  • 我想说他们都必须保证部分内容:您的 C++ 实现必须保证缓冲区已刷新,并且 close() 仅在 close 文件的相关系统调用之后返回已返回,内核必须保证在系统调用返回后,文件是可打开的,并且通过旧句柄所做的所有更改都是可见的,并且 VFS 必须保证正确处理缓存。我同意@BasileStarynkevitch 的观点:所有这些都应该成立,你不应该遇到问题。
  • 太好了 - 谢谢。如果你们中的一个写了一个答案,我会接受它。

标签: c++ linux file-io race-condition


【解决方案1】:

一旦文件被关闭,所有写入的数据都保证会从ofstream对象的缓冲区中刷新(因为此时您可以销毁它而不会丢失任何数据,并实际关闭文件如果需要,由析构函数在内部完成)。这并不意味着此时数据将物理存储在磁盘上(可能不会,因为操作系统磁盘驱动程序的缓存行为),但在同一操作系统中运行的任何程序都将能够一致地读取文件(因为操作系统随后将执行从缓存数据中的读取)。如果您需要将 OS 缓冲区刷新到磁盘(您的 secondprogram 不需要这样做以正确读取输入文件),那么您可能需要查看 <unistd.h> 中的 sync() 函数.

【讨论】:

    【解决方案2】:

    我之前错过了一个潜在的故障模式:当secondprogram无法打开文件时,您似乎没有办法恢复。问题不是close() 返回后文件可能被锁定/不一致,而是另一个与您完全无关的程序可能会在close()system() 之间打开文件(例如,一个 AV 扫描仪,某人 greping 通过包含该文件的目录,一个备份过程)。如果发生这种情况,secondprogram 将失败,即使 您的 程序运行正常。

    TL/DR:尽管一切都按预期工作,但您必须考虑secondprogram 可能无法打开文件的情况!

    【讨论】:

      【解决方案3】:

      根据cplusplus.com,当所有数据都写入磁盘后,该函数将返回。所以应该没有竞争条件。

      【讨论】:

      • 我认为这不是真的。 '任何挂起的输出序列都写入物理文件'是什么意思。可能是fstream 的内部缓冲区已刷新,因此对文件的所有更改对其他人都是可见的。如果标准要求close() 强制操作系统立即将其缓存写入磁盘,我会感到非常惊讶。
      • 您到 cplusplus.com 的链接并没有严格说明数据将在 fstream::close 返回时写入。几乎可以肯定不是:见stackoverflow.com/questions/705454/…
      • 这就是为什么我说根据,我没有实现C++ stdlib,所以不能告诉你。
      猜你喜欢
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      • 2011-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多