【问题标题】:C++ blocking flush [closed]C ++阻塞刷新[关闭]
【发布时间】:2019-06-17 09:09:15
【问题描述】:

我想刷新一个文件输出流 (fstream)。如果我按照通常的方式 (flush()) 执行此操作,程序不会等到文件的内容被实际写入,它会继续执行。为了说明这个问题,请考虑以下场景:

A 要求 B 向文件写入内容。 B 完成任务后立即返回。然后,A 访问该文件。不幸的是,在操作系统实际设法写入文件内容之前,B 已经完成。文件还不存在,A 崩溃了。

那么,有没有类似阻塞刷新的东西?

请注意,当 B 写入 cout 并且 B 的 stdout 被重定向到文件时,不会出现此问题。不幸的是,如果 B 将 cout 用于其他目的,则无法应用此解决方法。


编辑:我发现问题最终出在其他地方。对于那些感兴趣的人:

简短的版本是,该文件确实存在,但由于另一个程序仍在写入该文件而无法读取。

长版:假设我们收到程序 A,它可以被认为是某个算法问题的“解决方案”。问题是在线的,这意味着输入必须以小块的形式提供给 A。为此,我们创建了一个与 A 通信的程序 B。每当 A 发送答案时,B 都会发送下一个输入块。我们在 A 和 B 之间进行交互:我们创建一个 FIFO 文件 (mkfifo fifo),然后创建 A < fifo | B > fifo

我们想要捕获 A 的输出并查看它是否与某个目标输出文件 target.out 匹配。一种方法是让 B 打开一个文件流 (fstream fout("test.out", fstream::out)) 并将它从 A 读取的所有内容写入那里。另一个解决方案是:A < fifo | tee test.out | B > fifo。 A 和 B 交互完成后,我们运行diff test.out target.out 进行比较。

不幸的是,这两种解决方案都存在以下问题:一旦 A 完成,我们立即继续进行比较。 teeB,以test.out 的作者为准,尚未完成。如果是这样,则无法读取该文件(即使它存在,正如你们中的许多人所指出的那样)。

不考虑切换 A 和 B 的顺序,因为我们也在捕获 A 的返回码。 (必须报告解决方案在崩溃时已经崩溃。)

【问题讨论】:

  • 你的解释不是很清楚(对我来说)。显然B调用Flush时文件存在。请添加一些说明问题的代码。
  • 这是什么操作系统?通常,操作系统的文件系统有一个集成的缓冲层,因此即使数据还没有物理存储在磁盘上,另一个试图读取文件的程序仍然会“看到”它,因为文件系统驱动程序的读取例程知道查看文件系统的内存-在查看磁盘之前缓存。
  • 这是在linux上的,我没有在其他操作系统上测试过。
  • 您描述的场景不存在。如果 A 访问 B 应该写入的文件,即使该文件在磁盘上尚不存在,它也会成功。

标签: c++ linux flush


【解决方案1】:

为了抵御系统崩溃,您需要 fsync/fdatasync 系统调用。

来自 POSIX:

fsync() 函数应请求打开文件的所有数据 由 fildes 命名的描述符将被传输到存储设备 与由 fildes 描述的文件相关联。的性质 传输是实现定义的。 fsync() 函数不应 返回直到系统完成该操作或直到出现错误 检测到。

对于您在问题中描述的简单 IPC,您无需执行任何操作。

当 A 查看 B 已刷新到系统的信息时,该信息尚未写入磁盘并不重要。 A 不会从磁盘中获取它,它会从系统中获取它,并且无论数据是否已同步到永久存储,系统都会为其提供最新信息。

【讨论】:

  • 这只会影响 OS 文件缓存,有助于确保数据实际上在磁盘上(例如,在断电时的事务完整性),但 OS 已经提供了一致的视图跨进程的文件内容,即使没有同步到磁盘。
  • 好吧,现在我看到了编辑。
猜你喜欢
  • 1970-01-01
  • 2019-11-27
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 2017-09-08
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
相关资源
最近更新 更多