【问题标题】:Can you open the same file multiple times for writing?您可以多次打开同一个文件进行写入吗?
【发布时间】:2014-03-18 02:48:45
【问题描述】:

我们正在编写一个多线程应用程序,该应用程序执行一堆位旋转并将二进制数据写入磁盘。是否可以让每个线程std::fopen 同时写入同一个文件?理由是每个线程都可以完成自己的工作并拥有对可写文件的访问权限。

【问题讨论】:

  • 据我所知,写入硬盘并不是真正可线程化的事情(例如,一次只能有一个线程执行)。我可能是错的,其他人可能更能阐明这一点。它也可能是特定于操作系统的东西。为了更深入地解决您的问题,我相信如果该文件的句柄已经打开,大多数操作系统都会锁定对该文件的后续写入访问。
  • 并发访问单个文件:已解决问题。很久很久以前就解决了。
  • 嗯,没有足够的信息来回答这个问题。所有这些线程是否都在附加数据或写入随机位置?在不知道该问题的答案的情况下,没有人可以回答您的问题。

标签: c++


【解决方案1】:

std::fstream 具有根据 C stdio 库定义的功能。如果它真的被指定了,我会感到惊讶,但是两次打开同一个文件最可能的行为是多个内部缓冲区绑定到同一个文件描述符。

同时写入同一文件中的多个点的常用方法是 POSIX pwritewritev。此功能不被 C stdio 包装,并且通过扩展也不被 C++ iostreams 包装。但是,对同一个文件系统文件使用多个描述符也可能有效。

编辑: POSIX open 在 Mac OS X 中对同一文件调用两次会产生不同的文件描述符。因此,它可能适用于您的平台,但可能不便携。

一个明确的答案需要连接这些点:

  • C++ 标准规定 fstream 的工作方式类似于 C (stdio) 流。
  • C 标准定义了何时创建流(fopen 仅定义为将流与新打开的文件关联)。
  • POSIX 标准定义了其对 C 流的要求。
  • POSIX 定义了打开同一个文件两次的情况。

这比我目前的研究要多一些,但我敢肯定有人已经完成了这项工作。

【讨论】:

  • 呃……有人在这里添加了经过充分研究的 cmets,增加了更多深度,但版主删除了它们。我似乎记得 OS X 的行为是由 POSIX 保证的。
【解决方案2】:

我编写了一些高速多线程数据捕获实用程序,但输出到单独硬盘驱动器上的单独文件,然后进行后处理。

【讨论】:

    【解决方案3】:

    我似乎记得你可以让 fopen 不锁定文件,所以理论上这将允许不同的线程全部写入具有独立句柄的同一个文件。在实践中,您将遇到其他问题,即并发性。除非您实现一些同步,否则您的线程几乎肯定会互相踩踏并打乱结果。如果必须这样做,为什么不在所有线程中使用一个句柄?

    【讨论】:

      【解决方案4】:

      I/O 访问不是一个可并行化的任务(它不可能,你根本不能同时通过设备总线发送两个或多个数据地址)所以你最好实现一个队列,其中有许多线程发布他们的数据块,一个消费者实际将它们写入磁盘。

      【讨论】:

      • 当然不能:“使用 TCQ,驱动器可以自行决定如何对请求进行排序”。 TCQ 只是一种通过以最有效的方式对 I/O 请求进行排序和打包来提高驱动器性能的技术……并发写入没有什么神奇的 :-)
      • ... 并且驱动器不能有多个请求以进行最佳排序,除非您有某种方法可以同时发送多个请求。对于大多数程序,这将通过调用 read() 或 write() 的多个线程来完成。使用您提出的单 I/O 线程方法,驱动器无法知道 I/O 线程将来排队发送什么,因此无法利用该信息进行 TCQ。跨度>
      • 单线程 I/O 并不一定意味着驱动器无法打包请求并将其整理出来……大多数时候 I/O R/W 是缓冲的。无论如何,我的说法仍然成立:你不能同时拥有多个 I/O 访问。
      猜你喜欢
      • 2019-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多