【问题标题】:How to flush memory-mapped files using Boost's `mapped_file_sink` class?如何使用 Boost 的 `mapped_file_sink` 类刷新内存映射文件?
【发布时间】:2016-12-05 10:46:40
【问题描述】:

使用 Boost 库 version 1.62.0 和来自 Boost.IOStreamsmapped_file_sink 类。

我想把写入的数据刷到磁盘at will,但是没有mapped_file_sink::flush()的成员函数。

我的问题是:

  • 使用mapped_file_sink时如何刷新写入的数据?
  • 如果以上都做不到,为什么不呢,考虑到msync()FlushViewOfFile() 可用于可移植实现?

【问题讨论】:

    标签: c++ boost boost-iostreams


    【解决方案1】:

    如果您查看https://ned14.github.io/boost.afio/classboost_1_1afio_1_1v2__xxx_1_1map__handle.html 对提议的 Boost.AFIO v2 的映射文件支持,您会注意到也缺乏刷新映射文件视图的能力。

    原因是因为当映射视图在各方面与该文件的页面缓存缓冲区相同时,它在现代统一页面缓存内核上是多余的。因此,msync() 在此类内核上是无操作的,因为脏页已经排队等待写入存储,当系统决定它是合适的时候。您可以阻止您的进程,直到系统使用旧的 fsync() 写出该文件的所有脏页。

    以上所有不适用于 (a) 您的内核不是统一的页面缓存设计(QNX、NetBSD 等)或 (b) 您的文件驻留在网络文件系统上的情况。如果您处于 (a) 情况,最好完全避免内存映射 i/o,只需执行 read()write(),它们现在占操作系统的一小部分,让它们遭受性能不佳的困扰。对于 (b) 情况,强烈建议您将内存映射 i/o 与网络文件系统一起使用。只有不可变文件的只读映射有一个论点,否则不要这样做,除非您知道自己在做什么。回退到read()write(),这样更安全,更不容易出人意料。

    最后,您链接到了一个安全的文件删除程序。由于扩展区分配延迟或写分配时复制,这些程序不再可靠地与最近的文件系统一起工作。换句话说,当您重写现有文件的一部分时,它不会修改存储上的原始数据,而是实际上分配新的存储并将文件的范围列表指向新的链表。这允许在意外数据丢失后轻松恢复一致的文件系统。要安全地删除最近文件系统上的数据,您通常需要使用特殊的操作系统 API,尽管删除所有文件然后用随机数据填充可用空间可能会在大多数情况下安全地删除大部分有问题的数据。请注意,写入文件系统的副本可能不会在下一次垃圾收集例程触发或删除快照之前将释放的扩展区释放回可用空间池以进行新分配数天或数周。在这种情况下,随机填充可用空间不会安全地删除有问题的文件。如果所有这些都是问题,请使用 FAT32 作为您的文件系统,它非常简单,并且在其上重写数据确实会重写存储上的相同数据(但请注意,某些存储介质,例如 SSD 很可能也不会重写数据,这些也稍后将修改写入新存储和垃圾收集释放的范围)。

    【讨论】:

    • 我希望我能留在高层,尽管SDelete documentation 之前向我暗示我不能。感谢您的回答:我通常不会“接受”单一答案,因为这似乎没有必要;但是,既然你被不知名的人投了反对票,我不妨这样做。
    • 毫无疑问,我是 boost-dev 的众多粉丝之一。在我说我在这里回复后不久,它就被否决了。我所知道的最接近的便携式安全删除算法是删除您想要删除的所有文件,创建一个填充所有可用空间的文件,然后如果您的设备支持 TRIM,只需 fsync,然后删除该文件。如果不支持 TRIM,则用零填充,fsync,然后删除。这应该在大多数情况下安全地删除大部分数据,并且在支持 TRIM 的设备上它也相当快。感谢您的回答接受。
    猜你喜欢
    • 1970-01-01
    • 2014-11-16
    • 2013-06-19
    • 2016-01-08
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多