简体   繁体   English

使用VirtualProtect将页面标记为写时复制(Windows上的穷人分叉)

[英]Use VirtualProtect to mark pages as copy-on-write (poor-man's fork on windows)

I use VirtualAlloc(Ex) to allocate and commit a large range of pages. 我使用VirtualAlloc(Ex)来分配和提交大量页面。

Later in the execution I wish to "fork" that memory, launch a new process that can read it in it's current state, while the parent process treats it as copy-on-write memory. 稍后在执行中我希望“分叉”该内存,启动一个可以在其当前状态下读取它的新进程,而父进程将其视为写时复制内存。

Can this be done with VirtualAlloc(Ex) and VirtualProtect(Ex)? 可以使用VirtualAlloc(Ex)和VirtualProtect(Ex)完成吗?

This is trivial on posix systems thanks to fork(). 由于fork(),这在posix系统上是微不足道的。 Can I emulate just this part of fork efficiently on windows? 我可以在Windows上有效地模拟这部分fork吗?

Thanks, -Dan 谢谢,-Dan

I don't believe any of these quite answer the question posed by the original poster. 我不相信这些中的任何一个都能完全回答原始海报提出的问题。 Perhaps I might venture the following example. 也许我可以尝试下面的例子。 Suppose one has some data in "bufferA" and one copies it to "bufferB" and then modifies both buffers. 假设一个在“bufferA”中有一些数据,一个将它复制到“bufferB”,然后修改两个缓冲区。 Now one examines both buffers, and decides to copy either "bufferA" or "bufferB" to "bufferC" and make more modifications to "bufferC", and so forth. 现在检查两个缓冲区,并决定将“bufferA”或“bufferB”复制到“bufferC”并对“bufferC”进行更多修改,依此类推。

Assuming that the buffers are large and the modifications are small, the question is whether it would be an optimization to use the copy-on-write capability of the MMU on the host machine, and whether there is an API to allow this. 假设缓冲区很大且修改很小,问题是在主机上使用MMU的写时复制功能是否优化,以及是否有API允许这样做。

The use of memory mapped files doesn't quite work because, once one uses PAGE_WRITECOPY, there seems to be no way to say "now copy the virtual pages containing the changes". 使用内存映射文件并不是很有效,因为一旦使用PAGE_WRITECOPY,似乎没有办法说“现在复制包含更改的虚拟页面”。 For example, if "bufferA" and "bufferB" both were mappings of the same file, and at the time of the mapping one of them was marked "WRITECOPY", there seems to be no way to map those modifications to "bufferC". 例如,如果“bufferA”和“bufferB”都是同一文件的映射,并且在映射时其中一个标记为“WRITECOPY”,则似乎无法将这些修改映射到“bufferC”。 One can of course just copy the bits, but the question is whether there is a potential optimization. 当然可以只复制这些位,但问题是是否存在潜在的优化。

There is a function called VirtualCopy(), but that seems to be Windows CE specific, and works with physical addresses. 有一个名为VirtualCopy()的函数,但它似乎是特定于Windows CE的,并且与物理地址一起使用。 The question here is whether there is something like "VirtualCopy", but taking a virtual address as the source. 这里的问题是是否有类似“VirtualCopy”的东西,但是以虚拟地址为源。

Note that while "fork()" (on systems which have it) does this, one "fork's" the whole process, not just the buffer. 请注意,虽然“fork()”(在拥有它的系统上)执行此操作,但是“fork”是整个过程,而不仅仅是缓冲区。 There was a related discussion regarding "copy-on-write memcpy" here ( Can I do a copy-on-write memcpy in Linux? ). 这里有一个关于“copy-on-write memcpy”的相关讨论( 我可以在Linux上写一个copy-on-write memcpy吗? )。

So the API being sought might look something like this: void * VirualCopyVirtualAddressSpace( void* src, size_t length); 所以正在寻找的API可能如下所示:void * VirualCopyVirtualAddressSpace(void * src,size_t length);

So far, I have seen no API on any system which would allow the buffers to be copied either within a process or between existing processes. 到目前为止,我在任何系统上都没有看到API,它允许在进程内或现有进程之间复制缓冲区。 While I'm not an expert, I would have thought that copying a properly aligned segment of virtual memory via the copy-on-write mechanism would have be reasonably simple, at least within a single address space. 虽然我不是专家,但我认为通过写时复制机制复制正确对齐的虚拟内存段相当简单,至少在单个地址空间内。

I think you can do that if you use memory mapping (CreateFileMapping/MapViewOfFile) with PAGE_WRITECOPY. 如果您使用PAGE_WRITECOPY使用内存映射(CreateFileMapping / MapViewOfFile),我认为您可以这样做。

This example in MSDN might serve as starting point, if you change FILE_MAP_ALL_ACCESS to PAGE_WRITECOPY for the second process. 如果将FILE_MAP_ALL_ACCESS更改为第二个进程的PAGE_WRITECOPY,则MSDN中的示例可以作为起点。

If you want a consistent point-of-time copy behavior, you'll likely need to VirtualProtect() the mapped region with PAGE_WRITECOPY in the first process, so second process does not see any changes. 如果您想要一致的时间点复制行为,则可能需要在第一个进程中使用PAGE_WRITECOPY对映射区域进行VirtualProtect(),因此第二个进程看不到任何更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM