微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么malloc交替调用mmap和brk?

如何解决为什么malloc交替调用mmap和brk?

我是C和堆内存的新手,但仍在努力了解动态内存分配。

我跟踪了Linux系统调用,发现如果我使用malloc请求少量的堆内存,那么malloc将在内部调用brk

但是,如果我使用malloc请求大量的堆内存,那么malloc将在内部调用mmap

因此brkmmap之间必须有很大的区别,但是理论上我们应该能够使用brk分配堆内存,而不管请求的大小如何。那么,为什么malloc在分配大量内存时调用mmap

解决方法

那么为什么要在分配大容量内存时malloc调用mmap?

最简单的答案是提高效率,用于更新的Linux实现以及随之而来的更新的内存分配算法。但是请记住,这是一个非常依赖于实现的主题,并且对于所讨论的特定Linux OS的不同年份和风格,其理由为何会有所不同。

Here is fairly recent write-up关于低级部分mmap()brk()在Linux内存分配中的作用。而且,不是最近但仍然很相关的Linux Journal文章,其中包含一些非常适合此处主题的内容,包括:

对于非常大的请求,malloc()使用mmap()系统调用来查找 可寻址的内存空间。 此过程有助于减少负面影响 释放大块内存时内存碎片的影响 但被较小的,最近分配的块锁定 它们和分配空间的末尾。在这种情况下,实际上 使用brk()分配了该块,它将仍然无法使用 即使进程将其释放,也由系统执行。
(强调我的)

关于brk()
incidentally,“ ... mmap()在Unix的早期版本中不存在。brk()是当时增加进程数据段大小的唯一方法带有mmap()的Unix的第一个版本是80年代中期的SunOS,1990年的第一个开源版本是BSD-Reno。”。从那时起,内存分配算法的现代实现已进行了许多改进,从而得以重构,从而大大减少了使用brk()进行存储分配算法的需要。

,

mmap(与MAP_ANONYMOUS一起使用)分配了一块RAM,可以将其放置在进程的虚拟地址空间内的任何位置,并且可以稍后(通过munmap)进行独立地释放。所有其他分配中。

brk更改虚拟地址空间的单个连续“竞技场”的结束地址:如果增加该地址,它将为竞技场分配更多的内存,如果减少该虚拟地址空间,则它将在竞技场的内存分配不足。竞技场的尽头。因此,只有在进程不再需要连续范围的地址 时,才可以将用brk分配的内存释放回操作系统。

brk用于较小的分配,将mmap用于较大的分配是一种启发式方法,其假设是:较小的分配更有可能都具有相同的寿命,而较大的分配则更有可能寿命与其他任何分配的寿命都不相关。因此,大分配使用系统原语,该原语使它们可以与其他任何东西独立地解除分配,而小分配使用原本不分配的原语。

这种启发式方法不是很可靠。如果我没记错的话,当前一代malloc实现完全放弃了brk并使用mmap进行所有操作。我怀疑您正在查看的malloc实现(GNU C库中的实现,基于您的标记)非常老,并且主要继续使用,因为没有人敢于承担将其换出的风险。可能会可能但不一定会 会更好的新事物。

,

brk()是UNIX中分配内存的传统方法-它只是将数据区域扩展给定数量。 mmap()允许您分配独立的内存区域,而不受限于虚拟地址空间的单个连续块。

malloc()使用数据空间进行“小”分配,使用mmap()进行“大”分配,原因有很多,包括减少内存碎片。这只是实现细节,您不必担心。

也请检查此question

,

减少碎片通常是将mmap用于大型分配的原因。有关详细信息,请参见ryyker’s answer。但是我认为这并不是当今的真正好处。实际上,即使在大型池(虚拟地址空间,而不是堆)中,即使使用mmap仍然会有碎片。

mmap的最大优势是可丢弃性。

在使用sbrk分配内存时,如果实际使用了内存(以便内核在某个时刻映射物理内存),然后释放了内存,则内核本身无法知道,除非分配器还减少程序中断(如果释放的块不是程序中断下以前使用的最高块,则无法执行)。结果是就内核而言,该物理内存的内容变得“宝贵”。如果需要重新使用该物理内存,则必须确保它不会丢失其内容。因此,即使拥有过程不再关心页面,它也可能最终换出页面(这很昂贵)。

使用mmap分配内存时,释放内存不仅会将块返回到某个地方的池中;相应的虚拟内存分配返回给内核,并告诉内核不再需要任何相应的物理内存(脏的或其他)。然后,内核可以重新分配该物理内存的用途,而不必担心其内容。

,

我想强调另一个观点。

malloc是分配内存的系统函数。

您实际上不需要调试它,因为在某些实现中,它可能会为您提供来自静态“竞技场”(例如静态char数组)的内存。

在其他一些实现中,它可能只返回空指针。

如果您想了解锦葵的真正用途,建议您看看
http://gee.cs.oswego.edu/dl/html/malloc.html

Linux gcc malloc基于此。

您也可以看看jemalloc。它基本上使用相同的brk和mmap,但对数据的组织方式不同,通常“更好”。

研究愉快。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。