为什么malloc()交替调用mmap()和brk()?
我不熟悉C和堆内存,仍在努力理解动态内存分配 我跟踪了Linux系统调用,发现如果我使用为什么malloc()交替调用mmap()和brk()?,c,linux,linux-kernel,heap,dynamic-memory-allocation,C,Linux,Linux Kernel,Heap,Dynamic Memory Allocation,我不熟悉C和堆内存,仍在努力理解动态内存分配 我跟踪了Linux系统调用,发现如果我使用malloc请求少量堆内存,那么malloc会在内部调用brk 但是如果我使用malloc请求大量堆内存,那么malloc在内部调用mmap 因此,brk和mmap之间肯定有很大的区别,但理论上我们应该能够使用brk来分配堆内存,而不管请求的大小如何。那么,在分配大量内存时,为什么malloc调用mmap?mmap(与MAP\u ANONYMOUS一起使用时)会分配一块RAM,该RAM可以放在进程虚拟地址空间
malloc
请求少量堆内存,那么malloc
会在内部调用brk
但是如果我使用malloc
请求大量堆内存,那么malloc
在内部调用mmap
因此,brk
和mmap
之间肯定有很大的区别,但理论上我们应该能够使用brk
来分配堆内存,而不管请求的大小如何。那么,在分配大量内存时,为什么malloc
调用mmap
?mmap
(与MAP\u ANONYMOUS
一起使用时)会分配一块RAM,该RAM可以放在进程虚拟地址空间的任何位置,并且以后可以释放(使用munmap
)独立于所有其他分配
brk
更改虚拟地址空间中单个连续“竞技场”的结束地址:如果该地址增加,则会向竞技场分配更多内存;如果该地址减少,则会在竞技场结束时释放内存。因此,只有当进程不再需要竞技场末端的连续地址范围时,才能将分配有brk
的内存释放回操作系统
对于小分配使用brk
,对于大分配使用mmap
是一种启发式方法,其假设是小分配更有可能具有相同的寿命,而大分配更有可能具有与任何其他分配的寿命无关的寿命。因此,大的分配使用系统原语,允许它们独立于其他任何东西进行释放,而小的分配使用原语,而不是
这种启发式方法不太可靠。如果我没记错的话,当前一代的malloc
实现已经完全放弃了brk
,而是将mmap
用于一切。我怀疑您正在查看的malloc
实现(GNUC库中的一个,基于您的标记)非常旧,主要是因为没有人敢冒险将它换成更新的东西,而更新的东西可能会更好,但不一定会更好。那么,为什么malloc在分配大容量内存时调用mmap呢
简单的答案是提高Linux的新实现的效率,以及随之而来的更新的内存分配算法。但是请记住,这是一个非常依赖于实现的主题,对于所讨论的特定Linux操作系统的不同年份和风格,原因和原因会有很大的不同
关于底层部分mmap()
和brk()
在Linux内存分配中发挥作用。这是一篇不太新但仍然相关的文章,其中包含一些与本主题非常相关的内容,包括:
对于非常大的请求,malloc()使用mmap()系统调用来查找
可寻址内存空间。这个过程有助于减少负面影响
释放大内存块时内存碎片的影响
但被更小的、最近分配的块锁定
它们和分配的空间的末尾。事实上,在这种情况下
如果已使用brk()分配该块,则该块仍将不可用
即使进程释放了它,也由系统执行。(强调矿山) 关于
brk()
:“…mmap()在早期版本的Unix中不存在。
brk()
是当时增加进程数据段大小的唯一方法。使用mmap()的Unix的第一个版本是80年代中期的SunOS,第一个开源版本是1990年的BSD Reno。”。从那时起,内存分配算法的现代实现经过了许多改进,大大减少了对它们的需要,包括使用brk()
brk()
是UNIX中分配内存的一种传统方式,它只是将数据区域扩展了给定的数量mmap()
允许您分配独立的内存区域,而不限于单个连续的虚拟地址空间块
malloc()
将数据空间用于“小”分配,将mmap()
用于“大”分配,原因有很多,包括减少内存碎片。这只是一个您不必担心的实现细节
请检查一下。我想强调另一个观点 malloc是分配内存的系统函数 您实际上不需要调试它,因为在某些实现中,它可能会从静态“竞技场”(例如静态字符数组)中为您提供内存 在其他一些实现中,它可能只返回空指针 如果你想了解锦葵的真正用途,我建议你看看
Linux gcc malloc就是基于此 你也可以看看jemalloc。它基本上使用相同的brk和mmap,但数据组织方式不同,通常“更好”
愉快的研究。减少碎片通常被认为是
mmap
用于大型分配的原因;有关详细信息,请参阅。但我认为这不是现在真正的好处;实际上,即使使用mmap
,在更大的池(虚拟地址空间,而不是堆)中仍然存在碎片
mmap
的最大优点是可丢弃性
当使用sbrk
分配内存时,如果实际使用了内存(以便内核在某个点映射物理内存),然后释放了内存,内核本身就无法知道这一点,除非分配器也减少了程序中断(它会