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

3
例如,如果我这样做:
  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个回答

7

glibc手册表示这样做是可以的:

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

在一条命令中解除多个映射或者包含未映射空间在范围内都是安全的。也可以只解除现有映射的部分内容。但是,只有整个页面才能被删除。


4

POSIX规范说明

int munmap(void *addr, size_t len);

The munmap() function shall remove any mappings for those entire pages containing any part of the address space of the process starting at addr and continuing for len bytes.

对我而言,这个措辞清晰地表明,使用一次 munmap() 移除多个映射是可行的,任何符合规范的实现都应该支持。

2
我认为它应该能够工作。POSIX规范指出它会移除包含进程地址空间中从addr开始并延续len字节的任何部分的整个页面的映射。它唯一未指定的行为是:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接