Joe*_*Joe 13 c malloc operating-system memory-management mmap
64位寻址的地址空间绝对是巨大的.我有一个程序,将有mmap几个内存块,每个大小为100 - 500 MB.我将不可避免地重新映射几次,这可能会导致可用的连续空间出现碎片.
无论空间出现什么碎片,对于可用的地址空间来说肯定会很小.
我的问题是:鉴于这些限制,在正常情况下,我可以期望所有mmap请求成功(即由于碎片而不会失败)吗?他们失败的原因是什么?
我知道堆本身没有整个空间,但我认为它占绝大多数.
Mac OS/Linux.
Fra*_*kH. 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可以查询via getrlimit(),并且 - 在系统特定的限制内 - 调整via setrlimit.该ulimit命令使用这些.但是,它们返回/设置上限,即允许的总虚拟地址空间,包括进程可以创建的所有映射(通过mmap()或malloc后端sbrk()).但总地址空间大小不同于单个映射的最大大小...
鉴于此,即使在64位Linux上,也不会耗尽虚拟地址空间; 试试,测试mmap()相同的500GB文件,比方说,200次.mmap最终会失败.
简而言之:
mmap()一旦你离开虚拟地址空间,肯定会失败.有些令人惊讶的是,这在许多"64位"架构上是可行的,因为虚拟地址可能少于 64位有效位.确切的截止时间取决于您的CPU和操作系统,并且可以通过getrlimit(RLIMIT_AS)或设置通过查询上限setrlimit(RLIMIT_AS). mmap()/ munmap()以不同的顺序和不同大小的块,可以在64位上发生地址空间碎片.这最终将限制您可以映射为单个块的最大大小.预测何时会发生这种情况很难,因为它取决于您的"映射历史"和操作系统的虚拟地址空间分配算法.如果ASLR(地址空间布局随机化)由OS完成,则它可能是不可预测的,并且不完全可重现.malloc() 也会在系统(如Linux)上达到总VA限制时失败,其中过度使用允许您"询问"比系统中更多的内存(物理+交换).malloc()和mmap()同MAP_ANON和/或MAP_PRIVATE在物理+交换被耗尽,因为这些类型的映射需要通过实际的内存或交换后备存储将失败.小技术更新:像x86和SPARC上面提到的,新的ARMv8(64位ARM,被称为"AArch64"在Linux中)MMU也有一个"分裂"的地址空间/地址空间洞-在地址从64位中,只有40是相关的.Linux为用户提供39位0 ...,向前提供虚拟地址... 0xFFFFFFFF.FFFFFFFF,为内核提供39位,虚拟地址,因此限制为512GB(减去应用程序尝试时已使用的内容mmap).
请参阅此处的注释(来自AArch64架构启用程序内核补丁系列).