【问题标题】:Why does the memory mapped file ever need to be flushed when access is RDWR?当访问是 RDWR 时,为什么需要刷新内存映射文件?
【发布时间】:2013-11-18 19:26:34
【问题描述】:

我正在阅读 golang 的内存映射文件实现之一,https://github.com/edsrzf/mmap-go/。首先他描述了几种访问模式:

// RDONLY maps the memory read-only.
// Attempts to write to the MMap object will result in undefined behavior.
RDONLY = 0
// RDWR maps the memory as read-write. Writes to the MMap object will update the
// underlying file.
RDWR = 1 << iota
// COPY maps the memory as copy-on-write. Writes to the MMap object will affect
// memory, but the underlying file will remain unchanged.
COPY

但是在 gommap 测试文件中我看到了这个:

func TestReadWrite(t *testing.T) {
  mmap, err := Map(f, RDWR, 0)
  ... omitted for brevity...
  mmap[9] = 'X'
  mmap.Flush()

那么,如果访问模式是RDWR,为什么他需要调用Flush来确保将内容写入文件呢?

或者是操作系统管理这个,所以它只在它认为应该写的时候写?

如果是最后一个选项,请您更详细地解释一下 - 我读到的是,当操作系统内存不足时,它会写入文件并释放内存。这是正确的吗?它仅适用于 RDWR 还是仅适用于 COPY?

谢谢

【问题讨论】:

    标签: go mmap memory-mapped-files


    【解决方案1】:

    程序使用mmap 映射内存区域。然后它修改映射的区域。系统不需要立即将这些修改写回底层文件,因此对该文件(在ioutil.ReadAll 中)的read 调用可以返回文件的先前内容。

    系统会在您做出更改后的某个时间点将更改写入文件。 允许在进行更改后的任何时间将更改写入文件,但默认情况下不保证何时写入这些更改。您所知道的是(除非系统崩溃),更改将在将来的某个时间写入。

    如果您需要保证更改已在某个时间点写入文件,那么您必须调用msync。

    mmap.Flush 函数使用MS_SYNC 标志调用msync。当该系统调用返回时,系统已将修改写入底层文件,因此对read 的任何后续调用都将读取修改后的文件。

    COPY 选项将映射设置为MAP_PRIVATE,因此即使您使用msync(通过Flush 函数),您的更改也将永远写回文件中.

    阅读有关 mmap 和 msync 的 POSIX 文档以获取完整详细信息。

    【讨论】:

    • 谢谢,所以 RDWR 标志并不意味着它会立即被写入。系统是否仅在调用 mysync 或 munmap 时写入文件? “RDWR - 写入 MMap 对象将更新基础文件。”似乎暗示将来某个时候即使用户不调用 msync 或 munmap 也会写入这些更改。基本上你能评论问题的最后两段吗?谢谢!
    • @sofia:写入通常是“懒惰的”,尽管由于统一的虚拟内存系统,实际上它们大部分时间都是“即时的”(这不是保证 , 尽管)。即使数据没有写入磁盘,后续的读取操作通常仍然会从缓冲区缓存中提取正确的数据——但是,你不知道,没有保证。需要这种保证并且需要可移植(即不依赖于系统的实现)的程序必须刷新才能确定。
    • 如果我在一个循环中一次写入 100 个字节,最多 1KB,它会在中途被刷新吗?还是有任何保证它会等待所有 1KB 完成并最终在稍后的某个时间写入磁盘?
    • 系统可以中途刷新你的写入。
    猜你喜欢
    • 1970-01-01
    • 2020-05-20
    • 2014-11-16
    • 2012-06-24
    • 2017-10-07
    • 1970-01-01
    • 2017-01-18
    • 2020-08-16
    • 1970-01-01
    相关资源
    最近更新 更多