【问题标题】:Concurrently writing to file while reading it out using mmap在使用 mmap 读取文件的同时写入文件
【发布时间】:2014-03-27 05:26:11
【问题描述】:

情况是这样的。

  1. 大量数据缓冲区(应超过合理的 RAM 消费)正在由程序生成。

  2. 该程序同时提供一个 websocket,这将允许一个 web 客户端指定要查看的数据缓冲区的一小部分。

为了支持第一个目标,使用标准方法写入文件(我使用便携式 C-stdio fopenfwrite,因为它已被证明比各种“纯 C++”方法更快。没关系. 数据被附加到文件中;stdio 将缓冲写入并定期刷新它们。)

为了支持第二个目标(在 BSD 上,尤其是 iOS),打开文件(open 来自 sys/fcntl.h -- stdio.h 那样可移植)和内存映射(mmap 来自sys/mman.h——同上)。通过决定使用内存映射,我不得不放弃这段代码的一些可移植性。看来 Boost 是我可以考虑避免车轮改造的东西。

无论如何,我的问题是我应该如何执行此操作,因为至少会有两个线程:定期附加到文件的主程序线程和响应的网络(或工作线程)线程Web 请求并传递从映射到磁盘上文件的内存区域读取的数据。

假设文件开始时大小为 1024 字节,mmap 被称为最初映射 1024 字节。当主线程向文件中写入另外 512 个字节时,如何通知网络线程或知道有关文件当前实际大小的任何信息(以便它可以再次 munmapmmap 使用更大的缓冲区对应于新尺寸)?此外,如果我天真地这样做,我会警惕主线程报告已写入 512 字节的情况,因此另一个线程现在映射文件的 1536 字节,但并非所有新的 512 字节都实际写入磁盘然而(操作系统仍在努力编写它,也许)。现在会发生什么?会不会出现一些垃圾?我的程序会崩溃吗?

如何确定数据何时正确刷新?数据刷新后如何及时通知我,以便我可以对其进行内存映射?

特别是调用fflush 是保证文件现在已更新w.r.t 的唯一方法。流,然后我可以保证(一旦fflush 返回)内存映射可以访问新大小而不会发生访问冲突? fsync呢?

【问题讨论】:

  • 对于我目前正在做的事情,更重要的是不要减慢进程(额外的fflush/fsync),所以我现在想也许是最合适的方法是定期重新打开文件(当然是只读的)fseekftell 以检查其长度。

标签: c++ multithreading file-io mmap


【解决方案1】:

当您以mmap 的形式直接使用POSIX API 时,您也应该直接使用它来编写。 POSIX 和 LibC 接口不能很好地配合使用。

write 是一个系统调用,它将数据直接传输到内核。逐字节写入会很慢,但对于写入大缓冲区来说,速度会快一点,因为它的开销较小(fwrite 最终会在后台调用write)。而且fwrite+fflush 肯定更有效率,因为这可能最终会成为对write 的两次或多次调用,如果你直接调用write,它只是一个。

mmap 的文档对此不是很清楚,但您似乎不能请求比文件实际拥有的更多字节。

【讨论】:

  • 那么我怎样才能追加到文件中呢?我很确定您不能使用 mmap 附加到文件(使其比现在更大)。但我很想被证明是错误的。没有什么可以做到的,所以我也不能使用mmap 来进行附加,只是我认为没有办法做到这一点。似乎您是在告诉我“只使用write”......这......可能也可以,但我只是认为它比使用c std lib复杂得多。
  • 啊,对不起。您只是说使用write,因为这也是 POSIX API。
  • @StevenLu: 是的,我只是说当你使用 POSIX API write 来编写时会更容易,因为它是较低级别的,所以与 mmap 的交互会更明显.. mmap 不能用于追加;如果我正确阅读了文档(我不完全确定),如果您尝试传递比当前文件大小更大的len,它将失败。
  • 嗯,我仍然不知道这是否回答了如何同步我的并发内存映射读取以确保我不会出现段错误的基本问题......我怎么知道一旦我调用write,我随后对该数据(刚刚传递给内核的数据)的访问(通过来自不同线程的映射内存,不少于)不会是访问冲突?
  • 正是由于这种不确定性(如果我只是选择一些大小来回退,也会出现类似的不确定性),我认为我将求助于独立打开并使用cstdio 方法,并从调用 mmap 的线程定期执行此操作。这应该可以保证我永远不会试图越过边界阅读。
猜你喜欢
  • 1970-01-01
  • 2011-10-16
  • 2013-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多