【问题标题】:Does mmap always return higher addressmmap 是否总是返回更高的地址
【发布时间】:2011-12-14 12:12:40
【问题描述】:

mmap(当使用 MAP_ANONYMOUS 调用时,即用于分配内存时)是否总是返回比先前调用更高的内存地址?如果不是这样,有没有办法让它总是返回更高的地址?

【问题讨论】:

  • 你为什么需要它来做这个?
  • 好吧,在我的应用程序中,我将通过 mmap 分配的所有内存的起始地址保存在一个数组中,并且我需要在某些时候搜索它们。让它们以排序形式让我能够执行二进制搜索。你可以说,我可以在每次调用 mmap 之后对它们进行排序,但问题是这个数组需要从信号处理程序内部读取,而且你知道不能在信号处理程序内部使用互斥锁或信号量,这会成为一个问题如果某个线程在从信号处理程序内部读取数组时对数组进行排序。
  • 那么在创建映射的时候把映射的地址插入正确的位置呢?假设您不是每秒创建十亿个映射,这基本上是零成本,并且您的数组已排序。如果您无法为每个mmap 提供一个额外的memmove,那就有问题了。
  • @MetallicPriest 正如我在其他地方告诉你的(在另一个问题的另一个答复中),你可以尝试在 SIGSEGV 处理程序中使用互斥锁,我相信它通常可以在今天的 Linux 系统上运行,即使它不保证也不符合 Posix。
  • 两个cmets:(1)添加新条目时,可以对数组的一个副本进行排序,然后翻转指针。 (2) 排序到底有多重要?如果mmaped 区域的数量相当少,线性搜索可能是可行的。

标签: c linux 64-bit x86 mmap


【解决方案1】:

默认情况下,mmap 可以返回任何对齐页面边界的地址,以任何顺序。

如果您想强制返回的地址是您指定的地址,您可以使用MAP_FIXED 标志,但这不是很便携和可靠。这样,您就可以将代码与特定内核上的 mmap 的特定实现绑定在一起。

但无论如何,为什么总是需要比前一个更高的地址?可能更好的方法是更改​​程序的逻辑。

【讨论】:

    【解决方案2】:

    不一定,至少根据它的定义不是。

    而且我相信使用ASLR 可能会发生更高地址不再可用的情况,因此mmap 必须选择一些更低的地址范围。

    显然,在 32 位处理器(和内核)上,内存空间可能几乎被填满,因此当要求较大的 mmap-ed 范围时,内核应该找到一个合适的范围,并且可以在任何地方。

    如果你想要一个单调的方向,请使用sbrk(但我真的不建议使用它)。

    另一种可能性是在程序初始化时使用mmapMAP_NORESERVE 预先分配大量(例如几TB)的地址空间,并在该范围内再次调用mmapMAP_FIXED 以获得真正可用的空间(在更易于管理的块中,例如几十兆字节)。

    @MetallicPriest:你真的应该激励和解释更多你的问题。有那么神秘和诡异(甚至我都猜不出来所有的上下文),回答它们不是很有趣。

    【讨论】:

    • 这看起来是个不错的解决方案。我从 MAP_NORESERVE 了解到的是,当 mmap 被调用时,内核不会分配物理内存,但只有当您再次使用 MAP_FIXED 调用它时才会分配物理内存。所以第一次使用 MAP_NORESERVE 调用 mmap 实际上会保留内存地址而不需要物理内存,因此在该范围内调用 MAP_FIXED 是安全的,对吧?
    • 是的。 MAP_NORESERVE 的缺点是地址范围是保留的(所以普通的 mmapMAP_ANONYMOUS 不会得到它),但不是地址空间(在交换时)。访问MAP_NORESERVE-d 空间时,你也许可以得到SIGSEGV
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-24
    • 2017-07-04
    • 2012-02-27
    • 2016-05-16
    • 1970-01-01
    相关资源
    最近更新 更多