每一篇关于内存分配的文章似乎都解释了如何mmap
使用或如何sbrk
使用,而不考虑如何将这些与堆关联起来。
我已经收集到堆在内存分配中的作用几乎是微不足道的——事实上,我不确定它的作用:D,我请求有人让我感到困惑。
这是我的理解:
1) 当内存被分配时,未初始化数据段的末尾,BSS,被扩展。这种扩展(例如将地址移动x
到x-n
)是调用 的结果sbrk
。在这个模型中,内存被分配到将 BSS 段头的位置减少了的n
字节(假设每个地址对应一个字节) 。sbrk
这个模型现在已经过时了。有些人将堆定义为所有此类扩展的聚合空间。其他人没有——在后一种情况下,堆有什么作用?
2)在现代内存分配方案中,堆确实存在(出于什么原因,我也不确定)。为了分配内存,malloc
内部用于mmap
将数据存储到作为页面集合的内存区域中。这些内存区域独立于堆。
TLDR:
对于旧系统:如果内存分配存储在增加末端 BSS 的偏移量后获得的地址空间中,那么堆是否有任何用途?
对于较新的系统:假设 mmap 主要用于内存分配,那么堆的用途是什么?
在这两种情况下,堆真的有用吗?
mmap
并且sbrk
是内核提供的用于为进程分配地址空间的系统调用。这些调用改变了虚拟地址到物理页框的映射。在这些映射的地址限制之外寻址内存是一个严格的禁忌,并且会导致分段错误。这是内核提供给进程的低级接口,以brk
地址结尾的内存区域通常称为堆。内核不知道
malloc
orfree
,这些是 libc 中的库函数。Libc 维护数据结构并记录从内存分配的角度来看哪些内存区域是空闲的,例如 . 如果可以通过重用先前释放的内存区域来满足对的调用,则调用malloc
不一定会导致调用sbrk
或mmap
(取决于 Libc 如何实现动态内存分配)来扩展映射。malloc
“堆”是一个高级概念,而不是低级实现。
malloc()
在 C 中,堆是用于提供分配的任何内存池。这是一个有趣、简单的内存分配器实现:
这是一个糟糕的分配器,但对于正确类型的程序,如果你的系统和编译器容忍内存对齐之类的事情,它有点工作。它的堆是
heap[]
数组,它在编译时使用数组声明来构建它,而不是用sbrk()
or组装一个mmap()
。“真正的”分配器的工作方式相同。当
malloc()
被调用时,它会占用其内存池(其堆)的一小部分并将其保留用于该分配。有两个重要的区别:free()
分配,以便以后可以再次使用它。sbrk()
or )来增加其堆的大小。mmap()