在64位进程中,我的mmap / malloc请求是否会被拒绝?

时间:2011-02-07 15:33:36

标签: c memory-management operating-system malloc mmap

64位寻址的地址空间绝对是巨大的。我有一个程序将mmap几个内存块,每个大小为100 - 500 MB。我将不可避免地重新映射几次,这可能会导致可用的连续空间碎片化。

无论空间发生什么碎片,对于可用的地址空间来说,肯定会非常小。

我的问题是:鉴于这些限制,在正常情况下,我可以期望所有mmap请求成功(即由于碎片而不会失败)吗?他们失败的原因是什么?

我知道堆没有自己的整个空间,但我认为它占绝大多数。

Mac OS / Linux。

4 个答案:

答案 0 :(得分:27)

请注意" 64位操作系统的地址空间大小"不一定涵盖整个64位范围。

例如,在x64(64位x86,又名' AMD64')上,实际可用的虚拟地址范围仅为"" 2x128TB,即两个不相交的47位块中的48位。在某些SPARC系统上,它是2x2TB,或2x8TB(41/44位)。这是由于MMU在这些平台上的工作方式。

除了这些架构限制之外,操作系统布局地址空间的方式也起到了重要作用 例如,x64上的64位Windows将(甚至64位)应用程序的虚拟地址大小限制为8TB(每个内核和用户端 1 )。

在UN * X系统(包括Linux,MacOSX和* BSD)上,RLIMIT_AS可以通过getrlimit()查询,并且 - 在系统特定限制内 - 通过{{进行调整1}}。 setrlimit命令使用这些命令。但是,它们返回/设置上限,即允许的总虚拟地址空间,包括进程可以创建的所有映射(通过ulimitmmap()后端,malloc)。 但总地址空间大小不同于单个映射的最大大小...

鉴于此,即使在64位Linux上,也不会耗尽虚拟地址空间;试试,试试sbrk()相同的500GB文件,比方说,200次。 mmap最终会失败。

简而言之:

    一旦你离开虚拟地址空间,
  • mmap()肯定会失败。有些令人惊讶的是,在许多" 64bit"架构只是因为虚拟地址可能小于 64位有效位。确切的截止时间取决于您的CPU和操作系统,可以通过mmap()查询或通过getrlimit(RLIMIT_AS)设置上限。
  • 通过在不同的顺序和不同大小的块中经常使用setrlimit(RLIMIT_AS) / mmap(),可以在64位上发生地址空间碎片。这最终将限制您可以映射为单个块的最大大小。预测何时会发生这种情况很难,因为它取决于你的映射历史记录"和操作系统'虚地址空间分配算法。如果ASLR(地址空间布局随机化)由操作系统完成,则可能无法详细描述,并且不能完全重现。
  • munmap()也会在系统(如Linux)上达到VA总限制之前失败,而过度使用会让你“问”"比系统中更多的内存(物理+交换)。
  • 在未启用过度使用的计算机/操作系统上,malloc()malloc() mmap()和/或MAP_ANON都会在物理+交换耗尽时失败,因为这些类型的映射需要通过实际内存或交换进行后备存储。

技术更新不多:与上面提到的x86和sparc一样,新的ARMv8(64位ARM,称为" AArch64"在Linux中)MMU也有一个"分裂"地址空间/地址空间空洞 - 在地址中的64位中,只有40位是相关的。 Linux为用户提供39位,虚拟地址为MAP_PRIVATE以上,内核为39位,虚拟地址为0 ...,因此限制为512GB(减去应用程序尝试时已使用的内容) ... 0xFFFFFFFF.FFFFFFFF)。
请参阅comments here(来自AArch64架构启用程序内核补丁系列)。

答案 1 :(得分:8)

由于缺少物理内存(RAM +交换),

mmapmalloc可能会失败。通常,Unix标准说的是“允许进程的地址空间”的地址范围。除此之外,

  

如果广告功能返回   发生错误代码   困难,你要检查   那个代码,是的,即使是检查   你的代码大小的三倍   你的打字手指会产生疼痛,   因为如果你瘦了“它不能   发生在我身上,众神肯定会   因你的傲慢而惩罚你。

Spencer

答案 2 :(得分:0)

只需检查man mmap中的错误列表。

答案 3 :(得分:0)

嗯,OS / C库可以自由决定是否有足够的内存。你真的没办法知道它是如何决定的(它显然是特定于操作系统的,甚至可能是可调的),但是在某些时候操作系统可能会说“不再”了。

无法分配内存的可能原因:

  • Linux将overcommit内存,但这是可调的。根据配置方式,一旦超过RAM +交换,您就可以获得ENOMEM。
  • 如果使用ulimit设置了内存限制,则可能会更早获得ENOMEM