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

Sof*_*fia 7 mmap go 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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

谢谢

rob*_*off 10

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

进行更改后,系统在某个时刻更改写入文件.它允许在做出修改之后的任何时间将更改写入文件,但默认情况下使有关,当它写这些变化没有保证.所有你知道的是(除非系统崩溃),更改将在未来的某个时刻写入.

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

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

COPY选项将映射设置为MAP_PRIVATE,因此即使您使用(通过该功能),您的更改也不会写回文件.msyncFlush

阅读关于POSIX文件mmapmsync完整的细节.

  • @sofia:写入通常是"懒惰的",尽管由于统一的虚拟内存系统(但这不是_guaranteed_,但实际上它们在大多数情况下都是"立即的").即使数据没有写入磁盘,后续的读操作仍然会从缓冲区缓存中提取正确的数据 - 但是,你不知道,不能保证.需要此保证并且需要可移植的程序(即不依赖于系统的实现)必须冲洗以确保. (2认同)