我可以使用一次调用munmap()来取消映射位于连续虚拟内存范围内的两个内存映射吗?

时间:2013-03-30 08:44:01

标签: linux macos posix mmap

例如,如果我这样做:

  char *pMap1;          /* First mapping */
  char *pReq;           /* Address we would like the second mapping at */
  char *pMap2;          /* Second mapping */

  /* Map the first 1 MB of the file. */
  pMap1 = (char *)mmap(0, 1024*1024, PROT_READ, MAP_SHARED, fd, 0);
  assert( pMap1!=MAP_FAILED );

  /* Now map the second MB of the file. Request that the OS positions the
  ** second mapping immediately after the first in virtual memory.  */
  pReq = pMap1 + 1024*1024;
  pMap2 = (char *)mmap(pReq, 1024*1024, PROT_READ, MAP_SHARED, fd, 1024*1024);
  assert( pMap2!=MAP_FAILED );

  /* Unmap the mappings created above. */
  if( pMap2==pReq ){
    munmap(pMap1, 2 * 1024*1024);
  }else{
    munmap(pMap1, 1 * 1024*1024);
    munmap(pMap2, 1 * 1024*1024);
  }

操作系统确实将我的第二个映射放在请求的位置(所以 (pMap2 == pReq)条件为真),单次调用 munmap()用于释放所有分配的资源吗?

Linux手册页说“munmap()系统调用删除了映射 对于指定的地址范围......“,这表明这将起作用, 但我仍然有点紧张。即使它在Linux上运行, 有人知道这可能是多么便携吗?

非常感谢。

3 个答案:

答案 0 :(得分:5)

glibc手册说没关系:

  

munmap 将所有内存映射从(addr)移除到(addr + length)。长度   应该是映射的长度。

     

取消映射多个是安全的   在一个命令中映射,或包括范围中的未映射空间。它是   也可以仅取消映射现有映射的一部分。但是,只有   整个页面都可以删除。

答案 1 :(得分:3)

POSIX规范says

int munmap(void *addr, size_t len);
     

munmap()函数应删除包含从addr开始并继续len字节的进程地址空间的任何部分的整个页面的任何映射。

对我而言,措辞清楚地表明好像删除多个映射只有一个munmap()是正常的,并且应该得到任何合规实现的支持。

答案 2 :(得分:2)

我认为它应该有效。 POSIX spec表示删除了

  

包含从addr开始并继续len字节的流程地址空间的任何部分的整个页面的任何映射

它描述的唯一未指明的行为是:

  

如果未通过调用mmap()建立映射,则未指定此函数的行为。