【问题标题】:how can I detect whether a specific page is mapped in memory?如何检测特定页面是否映射到内存中?
【发布时间】:2012-01-11 20:40:18
【问题描述】:

我想检测特定页面是否已经映射到内存中。这里的目标是能够在使用固定内存地址调用 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;
}

我知道我可以打开并解析 /proc/self/maps 以确定已分配的内存范围,并从中推断我是否可以安全地使用 mmap 请求特定的内存范围,但我正在寻找合适的 API:有这种事吗?

【问题讨论】:

  • 不能直接用MAP_FIXED看看能不能成功吗?
  • 哈,我的示例代码不正确(即,第二个 mmap(刚刚编辑)缺少 MAP_FIXED)。我的观点是,如果内存范围已经分配,​​MAP_FIXED 不能确保您得到错误(如果您对此有疑问,可以运行代码或阅读相关手册页)
  • 顺便说一句,如果你想知道 MAP_FIXED 有什么好处,我也想:)
  • @MerickOWA 根据手册页,MAP_FIXED 将覆盖映射页面:如果 addr 和 len 指定的内存区域与任何现有映射的页面重叠,则重叠现有映射的一部分将被丢弃。 所以你不应该依赖MAP_FIXED

标签: c linux unix mmap


【解决方案1】:

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

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

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

编辑0:

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

ENOMEMaddr to addr + length contained unmapped memory.

【讨论】:

  • 0) 是的,“remap”不是正确的术语,但这里的问题不在于我覆盖了 ptr 变量(ptr 对 mmap 的两次调用都获得了相同的值)。问题是之前的内存映射在第二次调用 mmap 后消失了。 1)我不想要多个映射。我只想在固定地址映射某些东西,但在此之前,我想检查该地址是否已映射,因为 2)如果请求的固定地址已用于映射(MAP_FIXED 标志 I忘记了上面的示例代码对此没有任何改变)
  • mincore 似乎不是我想要的,因为它检查页面是否是常驻的,而不是地址范围是否有效。
  • 可以,但是你可以利用它的副作用来报告未映射的地址。
【解决方案2】:

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

【讨论】:

  • 注意:对于未映射的页面,msync() 可能会返回 0-1ENOMEM,因此这不是一个准确的解决方案。
  • 注意:调用msync 会使您的应用程序有点更稳定,以换取整个系统变得更慢。避免所有不必要的 msync,最好避免所有同步,还有其他方法可以确保应用程序的稳定性。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 2013-02-20
    • 1970-01-01
    • 2012-01-06
    相关资源
    最近更新 更多