当访问模式为RDWR(读写)时,为什么需要刷新内存映射文件呢?

huangapple go评论82阅读模式
英文:

Why does the memory mapped file ever need to be flushed when access is RDWR?

问题

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

// RDONLY 将内存映射为只读模式。
// 尝试对MMap对象进行写操作将导致未定义的行为。
RDONLY = 0
// RDWR 将内存映射为读写模式。对MMap对象的写操作将更新底层文件。
RDWR = 1 << iota
// COPY 将内存映射为写时复制模式。对MMap对象的写操作将影响内存,但底层文件将保持不变。
COPY

但在gommap的测试文件中,我看到了这样的代码:

func TestReadWrite(t *testing.T) {
mmap, err := Map(f, RDWR, 0)
... 省略部分代码...
mmap[9] = 'X'
mmap.Flush()

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

或者是操作系统在管理这个过程,只有在认为需要写入时才会进行写入?

如果是最后一种情况,请您能否详细解释一下——我所了解的是,当操作系统内存不足时,它会将内容写入文件并释放内存。这样理解对吗?这个过程只适用于RDWR还是只适用于COPY?

谢谢。

英文:

I was reading through one of golang's implementation of memory mapped files, https://github.com/edsrzf/mmap-go/. First he describes the several access modes:

// 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 &lt;&lt; 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

But in gommap test file I see this:

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

So why does he need to call Flush to make sure the contents are written to the file if the access mode is RDWR?

Or is the OS managing this so it only writes when it thinks it should?

If the last option, could you please explain it in a little more detail - what i read is that when the OS is low in memory it writes to the file and frees up memory. Is this correct and does it apply only to RDWR or only to COPY?

Thanks

答案1

得分: 13

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

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

如果你需要确保更改已在某个时间点写入文件中,那么你必须调用msync函数。

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

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

请阅读有关mmapmsync的POSIX文档以获取完整的详细信息。

英文:

The program maps a region of memory using mmap. It then modifies the mapped region. The system isn't required to write those modifications back to the underlying file immediately, so a read call on that file (in ioutil.ReadAll) could return the prior contents of the file.

The system will write the changes to the file at some point after you make the changes.
It is allowed to write the changes to the file any time after the changes are made, but by default makes no guarantees about when it writes those changes. All you know is that (unless the system crashes), the changes will be written at some point in the future.

If you need to guarantee that the changes have been written to the file at some point in time, then you must call msync.

The mmap.Flush function calls msync with the MS_SYNC flag. When that system call returns, the system has written the modifications to the underlying file, so that any subsequent call to read will read the modified file.

The COPY option sets the mapping to MAP_PRIVATE, so your changes will never be written back to the file, even if you using msync (via the Flush function).

Read the POSIX documentation about mmap and msync for full details.

huangapple
  • 本文由 发表于 2013年11月19日 03:26:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/20056099.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定