Win32内存映射文件的部分取消映射

时间:2010-09-08 01:08:42

标签: winapi posix mmap

我有一些代码(我无法更改),我需要在本机Win32环境中工作。此代码调用mmap()munmap(),因此我使用CreateFileMapping()MapViewOfFile()等创建了这些函数,以完成相同的操作。最初这很好用,代码能够按预期访问文件。不幸的是,代码会继续到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()函数就足够了。

2 个答案:

答案 0 :(得分:2)

在UnmapViewOfFile的MSDN Library文档中非常明确:

  

lpBaseAddress
指向的指针   a的映射视图的基址   要取消映射的文件。这个   值必须与值相同   之前的电话回来了   MapViewOfFile或MapViewOfFileEx   功能

您可以通过取消旧映射并创建新映射来更改映射。从内存管理的角度来看,不能很好地支持取消映射的碎片,也不会产生任何有用的副作用。您不希望冒险将地址空间分段。

你必须以不同的方式做到这一点。

答案 1 :(得分:0)

您可以跟踪每个映射以及客户端仍分配了多少页面,并且只有在该计数器达到零时才释放映射。中间部分仍然会被映射,但无论如何都没关系,因为客户端无论如何都不会访问该内存。

通过此接口创建内存映射的全局字典。当映射请求通过时,记录该范围内的地址,大小和页数。发出取消映射请求时,找出哪个映射拥有该地址,并减少页面计数所释放的页数。当该计数达到零时,实际上取消映射视图。