c - 在 malloc 中,为什么要使用 brk?为什么不直接使用 mmap?

标签 c linux malloc mmap brk

malloc 的典型实现使用brk/sbrk 作为从操作系统申请内存的主要方式。但是,他们还使用 mmap 来获取大分配的 block 。使用 brk 而不是 mmap 真的有好处吗,还是只是传统?用 mmap 做这一切不是同样有效吗?

(注意:我在这里互换使用 sbrkbrk 因为它们是同一个 Linux 系统调用 brk 的接口(interface)。)


作为引用,这里有一些描述 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 引入了一些可能不必要的额外复杂性:

Allocated Arena - the main arena uses the application's heap. Other arenas use mmap'd heaps. To map a chunk to a heap, you need to know which case applies. If this bit is 0, the chunk comes from the main arena and the main heap. If this bit is 1, the chunk comes from mmap'd memory and the location of the heap can be computed from the chunk's address.

[Glibc malloc 派生自ptmalloc,派生自dlmalloc ,始于 1987 年。]


jemalloc联机帮助页 ( http://jemalloc.net/jemalloc.3.html) 是这样说的:

Traditionally, allocators have used sbrk(2) to obtain memory, which is suboptimal for several reasons, including race conditions, increased fragmentation, and artificial limitations on maximum usable memory. If sbrk(2) is supported by the operating system, this allocator uses both mmap(2) and sbrk(2), in that order of preference; otherwise only mmap(2) is used.

因此,他们甚至在这里说 sbrk 不是最理想的,但他们仍然使用它,即使他们已经不厌其烦地编写代码以使其在没有它的情况下也能正常工作。

[jemalloc 的编写始于 2005 年。]

更新:再考虑一下,关于“按优先顺序”的那一点给了我一条询问线。为什么优先顺序?他们只是使用 sbrk 作为回退以防 mmap 不受支持(或缺少必要的功能),还是进程有可能进入某种状态使用 sbrk 而不是 mmap?我会查看他们的代码,看看我是否能弄清楚它在做什么。


我问这个问题是因为我正在用 C 语言实现一个垃圾收集系统,到目前为止我认为没有理由使用 mmap 之外的任何东西。不过,我想知道我是否遗漏了什么。

(在我的例子中,我还有一个避免 brk 的额外原因,那就是我可能需要在某些时候使用 malloc。)

最佳答案

系统调用 brk() 的优点是只有一个数据项来跟踪内存使用情况,这也与堆的总大小直接相关。

自 1975 年的 Unix V6 以来,它一直采用完全相同的形式。请注意,V6 支持 65,535 字节的用户地址空间。因此,没有太多考虑管理超过 64K 的数据,当然不是 TB。

使用 mmap 似乎是合理的,直到我开始想知道如何改变或添加垃圾收集可以使用 mmap没有重写分配算法.

这能很好地与 realloc()fork() 等一起使用吗?

关于c - 在 malloc 中,为什么要使用 brk?为什么不直接使用 mmap?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55768549/

相关文章:

c - 为什么 &(&i) 在 C 中无效?

我可以通过 IEEE double 往返对齐指针吗?

c++ - ARM交叉编译,多重继承段错误

linux - 如何在 TAO Corba 的特定端口启动进程?

c - 从矩阵读取,用 malloc 分配,AddressSanitizer : heap-buffer-overflow

c - 开关和默认: for C

c - 使用较旧的 glibc 监视 Linux 中的文件更改

linux - 不能直接用 "java"命令运行java程序

iphone - Guard Malloc 立即发现 EXC_BAD_ACCESS 错误。为什么不一直使用呢?

c - 如何在c中正确分配和打印结构指针?