【发布时间】:2014-03-27 05:26:11
【问题描述】:
情况是这样的。
大量数据缓冲区(应超过合理的 RAM 消费)正在由程序生成。
该程序同时提供一个 websocket,这将允许一个 web 客户端指定要查看的数据缓冲区的一小部分。
为了支持第一个目标,使用标准方法写入文件(我使用便携式 C-stdio fopen 和 fwrite,因为它已被证明比各种“纯 C++”方法更快。没关系. 数据被附加到文件中;stdio 将缓冲写入并定期刷新它们。)
为了支持第二个目标(在 BSD 上,尤其是 iOS),打开文件(open 来自 sys/fcntl.h -- 不 像 stdio.h 那样可移植)和内存映射(mmap 来自sys/mman.h——同上)。通过决定使用内存映射,我不得不放弃这段代码的一些可移植性。看来 Boost 是我可以考虑避免车轮改造的东西。
无论如何,我的问题是我应该如何执行此操作,因为至少会有两个线程:定期附加到文件的主程序线程和响应的网络(或工作线程)线程Web 请求并传递从映射到磁盘上文件的内存区域读取的数据。
假设文件开始时大小为 1024 字节,mmap 被称为最初映射 1024 字节。当主线程向文件中写入另外 512 个字节时,如何通知网络线程或知道有关文件当前实际大小的任何信息(以便它可以再次 munmap 和 mmap 使用更大的缓冲区对应于新尺寸)?此外,如果我天真地这样做,我会警惕主线程报告已写入 512 字节的情况,因此另一个线程现在映射文件的 1536 字节,但并非所有新的 512 字节都实际写入磁盘然而(操作系统仍在努力编写它,也许)。现在会发生什么?会不会出现一些垃圾?我的程序会崩溃吗?
如何确定数据何时正确刷新?数据刷新后如何及时通知我,以便我可以对其进行内存映射?
特别是调用fflush 是保证文件现在已更新w.r.t 的唯一方法。流,然后我可以保证(一旦fflush 返回)内存映射可以访问新大小而不会发生访问冲突? fsync呢?
【问题讨论】:
-
对于我目前正在做的事情,更重要的是不要减慢进程(额外的
fflush/fsync),所以我现在想也许是最合适的方法是定期重新打开文件(当然是只读的)fseek和ftell以检查其长度。
标签: c++ multithreading file-io mmap