为什么在访问RDWR时需要刷新内存映射文件?

时间:2013-11-18 19:26:34

标签: go mmap memory-mapped-files

我正在阅读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?

由于

1 个答案:

答案 0 :(得分:10)

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

系统在您进行更改后的某个时刻将更改写入文件。 在进行更改后的任何时候都可以允许将更改写入文件,但默认情况下不保证何时写入这些更改。所有你知道的是(除非系统崩溃),这些变化将在未来的某个时刻写出。

如果您需要保证在某个时间点已将更改写入文件,则必须致电msync

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

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

有关详细信息,请阅读有关mmapmsync的POSIX文档。