windows 上的写时复制文件映射

Copy-on-write file mapping on windows

我有 3 个进程通过命名管道进行通信:服务器、编写器、reader。基本思想是 writer 可以在 server 上存储巨大的 (~GB) 二进制 blob,而 reader(s) 可以找回。但不是在命名管道上发送数据,而是使用内存映射。

服务器创建一个未命名的文件备份映射CreateFileMappingPAGE_READWRITE保护,然后将句柄复制到writer 。在 writer 完成其工作后,句柄被复制到任意数量的感兴趣的 readers.

编写器FILE_MAP_WRITE模式下将句柄映射到MapViewOfFile

readerFILE_MAP_READ|FILE_MAP_COPY模式下将句柄映射为MapViewOfFile

reader 上,我想要写时复制语义,因此只要只读取映射,它就会在所有 reader 实例之间共享.但是如果 reader 想要写入它(例如,就地解析或图像处理),影响应该限制在尽可能少的复制页面数量的修改过程中。

问题
reader 尝试写入映射时,它会因分段错误而死,就好像没有考虑 FILE_MAP_COPY 一样。 上述方法有什么问题?根据 MSDN,这应该有效...

我们在 linux 上也实现了相同的机制(mmap 和 fd 传入 AF_UNIX 辅助缓冲区)并且它按预期工作。

这里的问题是MapViewOfFile bad designed or/and documented. this is shell (with restricted functionality) over ZwMapViewOfSection. the dwDesiredAccess parameter of MapViewOfFile converted to Win32Protect parameter of ZwMapViewOfSection

FILE_MAP_READ|FILE_MAP_COPY 组合转换为 PAGE_READONLY 页面保护,因为这样你会在写入时遇到页面错误。

你只需要使用 FILE_MAP_COPY 标志 - 它转换为 PAGE_WRITECOPY 页面保护,在这种情况下一切都会起作用。

最好的办法当然是直接使用ZwMapViewOfSection加上PAGE_WRITECOPY页面保护

TL:DR: RbMm 是正确的,您必须将 just FILE_MAP_COPY 传递给 MapViewOfFile 以获得写时复制行为。

当前的 Microsoft 文档不正确,它错误地指出 FILE_MAP_COPY 可以与 FILE_MAP_<ALL_ACCESS|READ|WRITE> 进行“或”运算。

查看旧版本的 MSDN it correctly says 您必须选择一种访问模式:

Type of access to the file view and, therefore, the protection of the pages mapped by the file. This parameter can be one of the following values.

  • FILE_MAP_WRITE
  • FILE_MAP_READ
  • FILE_MAP_ALL_ACCESS
  • FILE_MAP_COPY

不再相关但仍然令人惊讶,在 Windows 95/98/ME 上,写时复制行为仅适用于文件,写入 are 传播到在其他进程中的意见!