如何检测特定页面是否映射到内存中?

时间:2021-07-27 06:08:07

I would like to detect whether or not a specific page has already been mapped in memory. The goal here is to be able to perform this check before calling mmap with a fixed memory address. The following code illustrates what happens in this case by default: mmap silently remaps the original memory pages.

我想检测一个特定的页面是否已经被映射到内存中。这里的目标是能够在调用具有固定内存地址的mmap之前执行此检查。下面的代码演示了默认情况下发生的情况:mmap默默地重新映射原始内存页。

#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
  int page_size;
  void *ptr;
  page_size = getpagesize();
  ptr = mmap(0, 10 * page_size, PROT_READ | PROT_WRITE,
             MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
  if (ptr == MAP_FAILED) {
    printf ("map1 failed\n");
    return 1;
  }
  ((int *)ptr)[0] = 0xdeadbeaf;
  ptr = mmap(ptr, 2 * page_size, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
  if (ptr == MAP_FAILED) {
    printf ("map2 failed\n");
    return 1;
  }
  if (((int *)ptr)[0] != 0xdeadbeaf) {
    printf ("oops, data gone !\n");
  }
  return 0;
}

I understand that I could open and parse /proc/self/maps to figure out which memory range has been allocated and infer from that if I can safely request a specific memory range with mmap but I am looking for a proper API: is there such a thing ?

我理解我可以打开并解析/proc/self/maps,以确定已经分配了哪些内存范围,并由此推断,如果我可以安全地使用mmap请求一个特定的内存范围,但我正在寻找一个合适的API:是否存在这种情况?

3 个解决方案

#1


6  

msync(addr, len, 0) and checking for ENOMEM seems to work (with a fairly superficial test).

msync(addr, len, 0)和ENOMEM检查似乎是有效的(通过一个相当肤浅的测试)。

#2


3  

This doesn't "remap" the memory, but creates another mapping at different address (since the one you give it is already taken, and it's treated as a hint anyway). The old one is still valid, you just lose the reference to it since you overwrite the ptr variable.

这并不是“重新映射”内存,而是在不同的地址创建另一个映射(因为您给出的那个地址已经被占用了,而且无论如何它都被当作一个提示)。旧的仍然有效,因为覆盖了ptr变量,所以就失去了对它的引用。

If you want to create multiple mappings to the same memory like that look into shm_open(2).

如果您想创建到相同内存的多个映射,请查看shm_open(2)。

If you just want to check if address is mapped then the MAP_FIXED trick pointed out by @MerickOWA should work.

如果您只是想检查地址是否被映射,那么@MerickOWA指出的MAP_FIXED方法应该可以工作。

Edit 0:

You are right about MAP_FIXED, it doesn't help in this case. What you might try is mincore(2). One of the errors it returns is:

关于MAP_FIXED,您是对的,在这种情况下没有帮助。你可以试试mincore(2)。它返回的错误之一是:

ENOMEMaddr to addr + length contained unmapped memory.

ENOMEMaddr到addr +长度包含未映射内存。

#3


0  

On QNX, you can use mem_offset() and posix_mem_offset() and check the contents of contig_len on output, comparing it with the length input parameter.

在QNX上,可以使用mem_offset()和posix_mem_offset()检查输出上的contig_len的内容,并将其与长度输入参数进行比较。

#1


6  

msync(addr, len, 0) and checking for ENOMEM seems to work (with a fairly superficial test).

msync(addr, len, 0)和ENOMEM检查似乎是有效的(通过一个相当肤浅的测试)。

#2


3  

This doesn't "remap" the memory, but creates another mapping at different address (since the one you give it is already taken, and it's treated as a hint anyway). The old one is still valid, you just lose the reference to it since you overwrite the ptr variable.

这并不是“重新映射”内存,而是在不同的地址创建另一个映射(因为您给出的那个地址已经被占用了,而且无论如何它都被当作一个提示)。旧的仍然有效,因为覆盖了ptr变量,所以就失去了对它的引用。

If you want to create multiple mappings to the same memory like that look into shm_open(2).

如果您想创建到相同内存的多个映射,请查看shm_open(2)。

If you just want to check if address is mapped then the MAP_FIXED trick pointed out by @MerickOWA should work.

如果您只是想检查地址是否被映射,那么@MerickOWA指出的MAP_FIXED方法应该可以工作。

Edit 0:

You are right about MAP_FIXED, it doesn't help in this case. What you might try is mincore(2). One of the errors it returns is:

关于MAP_FIXED,您是对的,在这种情况下没有帮助。你可以试试mincore(2)。它返回的错误之一是:

ENOMEMaddr to addr + length contained unmapped memory.

ENOMEMaddr到addr +长度包含未映射内存。

#3


0  

On QNX, you can use mem_offset() and posix_mem_offset() and check the contents of contig_len on output, comparing it with the length input parameter.

在QNX上,可以使用mem_offset()和posix_mem_offset()检查输出上的contig_len的内容,并将其与长度输入参数进行比较。