代码之家  ›  专栏  ›  技术社区  ›  Tim Sylvester

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

  •  0
  • Tim Sylvester  · 技术社区  · 14 年前

    我有一些代码(我无法更改)需要在本机win32环境中工作。此代码调用 mmap() munmap() ,因此我使用 CreateFileMapping() , MapViewOfFile() 等等,完成同样的事情。最初,这个方法很好,代码能够按预期访问文件。不幸的是,代码继续 MunPMAP() 文件中不再需要的选定部分。

    x = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
    ... 
    munmap(x, hdr_size);
    munmap(x + foo, bar);
    ...
    

    不幸的是,当您将指针传递到映射范围的中间时 UnmapViewOfFile() 它会破坏整个映射。更糟糕的是,我看不出我如何能够检测到这是一个局部的联合国地图请求,而忽略它。

    我试过打电话 VirtualFree() 在范围内,但是,毫不奇怪,这会产生错误\无效\参数。

    我开始认为我将不得不使用静态/全局变量来跟踪所有打开的内存映射,这样我就可以检测和忽略部分未映射,但我希望您有一个更好的主意…

    编辑:

    因为我在上面不够明确:unmapviewoffile的文档不能准确地反映该函数的行为。

    取消整个视图的映射和重新映射片段不是一个好的解决方案,因为您只能 建议 新映射的基地址,您不能真正控制它。的语义 MunPMAP() 不允许更改静态映射部分的基址。

    我真正需要的是找到已映射内存区域的基地址和大小的方法。

    伊迪丝2:既然我这样重述这个问题,看起来 VirtualQuery() 功能就足够了。

    2 回复  |  直到 14 年前
        1
  •  2
  •   Hans Passant    14 年前

    对于unmapviewoffile,它在msdn库文档中非常明确:

    LPASBASE地址
    指向的指针 映射视图的基地址 要取消映射的文件。这个 价值必须是 完全相同的 价值观 前一次调用返回 mapviewoffile或mapviewoffileex 功能。

    通过取消映射旧映射并创建新映射来更改映射。从内存管理的角度来看,不支持取消映射位和段,也不会有任何有用的副作用。您不想冒险让地址空间碎片化。

    你必须以不同的方式来做。

        2
  •  0
  •   Chris Smith    14 年前

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

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