malloc使用brk/sbrk作为从操作系统申请内存的主要方式的典型实现。但是,它们也用于mmap获取大分配的块。使用brk而不是有真正的好处mmap,还是只是传统?用它来做这一切难道不一样mmap吗?
(注意:我在这里使用sbrk和brk互换,因为它们是同一个 Linux 系统调用的接口,brk。)
作为参考,这里有一些描述 glibc 的文档malloc:
GNU C 库参考手册:GNU 分配器
https://www.gnu.org/software/libc/manual/html_node/The-GNU-Allocator.html
glibc wiki:Malloc 概述
https://sourceware.org/glibc/wiki/MallocInternals
这些文档描述的sbrk是用于为小分配声明主要区域,mmap用于声明次要区域,mmap也用于为大对象声明空间(“比页面大得多”)。
使用应用程序堆(用 声明sbrk)并mmap引入了一些可能不必要的额外复杂性:
分配的竞技场 - 主竞技场使用应用程序的堆。其他竞技场使用
mmap'd heaps。要将块映射到堆,您需要知道适用哪种情况。如果该位为 0,则该块来自主竞技场和主堆。如果该位为 1,则块来自mmap'd 内存,并且堆的位置可以从块的地址计算。
【glibc mallocptmalloc派生自dlmalloc, dlmalloc 始于 1987 年。】
jemalloc手册页(http://jemalloc.net/jemalloc.3.html)有这样的说法:
传统上,分配器用于
sbrk(2)获取内存,这是次优的,原因有几个,包括竞争条件、增加的碎片和对最大可用内存的人为限制。如果sbrk(2)操作系统支持,则此分配器mmap(2)按优先顺序同时使用和 sbrk(2);否则仅mmap(2)使用。
因此,他们甚至在这里说这sbrk是次优的,但他们仍然使用它,即使他们已经费心编写代码以便没有它也能正常工作。
[jemalloc 的编写始于 2005 年。]
更新:再想一想,关于“按优先顺序”的那一点给了我一条询问线。为什么是优先顺序?它们是否只是在不支持(或缺少必要的功能)sbrk的情况下用作后备mmap,或者该过程是否有可能进入某种可以使用sbrk但不能使用的状态mmap?我会看看他们的代码,看看我是否能弄清楚它在做什么。
我问是因为我正在用 C 实现一个垃圾收集系统,到目前为止,我认为没有理由使用除mmap. 不过,我想知道我是否缺少某些东西。
(在我的情况下,我还有一个额外的理由要避免brk,那就是我可能需要malloc在某些时候使用。)