Win32 内存映射文件的部分取消映射
我有一些代码(我无法更改)需要在本机 Win32 环境中工作。此代码调用 mmap()
和 munmap()
,因此我使用 CreateFileMapping()
、MapViewOfFile()< 创建了这些函数/code> 等来完成同样的事情。最初,这工作正常,并且代码能够按预期访问文件。不幸的是,代码继续执行
munmap()
文件中不再需要的选定部分。
x = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
...
munmap(x, hdr_size);
munmap(x + foo, bar);
...
不幸的是,当您将指针传递到映射范围的中间时,UnmapViewOfFile()
会破坏整个映射。更糟糕的是,我不知道如何能够检测到这是部分取消映射请求并忽略它。
我尝试在该范围内调用VirtualFree()
,但不出所料,这会产生 ERROR_INVALID_PARAMETER。
我开始认为我将不得不使用静态/全局变量来跟踪所有打开的内存映射,以便我可以检测并忽略部分取消映射,但我希望你有一个更好的想法......
编辑:
因为我不是'上面不够明确:UnMapViewOfFile 的文档没有准确反映该函数的行为。
取消映射整个视图并重新映射各个部分并不是一个好的解决方案,因为您只能为新映射建议一个基地址,而无法真正控制它。 munmap()
的语义不允许更改仍然映射部分的基地址。
我真正需要的是一种找到已映射内存区域的基地址和大小的方法。
edit2:现在我以这种方式重述了问题,看起来 VirtualQuery() 函数就足够了。
I have some code (which I cannot change) that I need to get working in a native Win32 environment. This code calls mmap()
and munmap()
, so I have created those functions using CreateFileMapping()
, MapViewOfFile()
, etc., to accomplish the same thing. Initially this works fine, and the code is able to access files as expected. Unfortunately the code goes on to munmap()
selected parts of the file that it no longer needs.
x = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
...
munmap(x, hdr_size);
munmap(x + foo, bar);
...
Unfortunately, when you pass a pointer into the middle of the mapped range to UnmapViewOfFile()
it destroys the entire mapping. Even worse, I can't see how I would be able to detect that this is a partial un-map request and just ignore it.
I have tried calling VirtualFree()
on the range but, unsurprisingly, this produces ERROR_INVALID_PARAMETER.
I'm beginning to think that I will have to use static/global variables to track all the open memory mappings so that I can detect and ignore partial unmappings, but I hope you have a better idea...
edit:
Since I wasn't explicit enough above: the docs for UnMapViewOfFile do not accurately reflect the behavior of that function.
Un-mapping the whole view and remapping pieces is not a good solution because you can only suggest a base address for a new mapping, you can't really control it. The semantics of munmap()
don't allow for a change to the base address of the still-mapped portion.
What I really need is a way to find the base address and size of a already-mapped memory area.
edit2: Now that I restate the problem that way, it looks like the VirtualQuery()
function will suffice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
UnmapViewOfFile 的 MSDN 库文档中非常明确:
您可以通过取消旧映射并创建新映射来更改映射。取消映射的部分并没有得到很好的支持,从内存管理的角度来看它也不会有任何有用的副作用。您不想冒地址空间碎片化的风险。
你必须以不同的方式来做这件事。
It is quite explicit in the MSDN Library docs for UnmapViewOfFile:
You changing the mapping by unmapping the old one and creating a new one. Unmapping bits and pieces isn't well supported, nor would it have any useful side-effects from a memory management point of view. You don't want to risk getting the address space fragmented.
You'll have to do this differently.
您可以跟踪每个映射以及客户端仍然分配的页数,并且仅在计数器达到零时才释放映射。中间部分仍然会被映射,但这并不重要,因为客户端无论如何都不会访问该内存。
通过此接口创建内存映射的全局字典。当映射请求通过时,记录该范围内的地址、大小和页数。当发出取消映射请求时,找出哪个映射拥有该地址,并将页计数减少正在释放的页数。当该计数达到零时,真正取消映射视图。
You could keep track each mapping and how many pages of it are still allocated by the client and only free the mapping when that counter reaches zero. The middle sections would still be mapped, but it wouldn't matter since the client wouldn't be accessing that memory anyway.
Create a global dictionary of memory mappings through this interface. When a mapping request comes through, record the address, size and number of pages that are in the range. When a unmap request is made, find out which mapping owns that address and decrease the page count by the number of pages that are being freed. When that count reaches zero, really unmap the view.