Dlmalloc是目前一个十分流行的内存分配器,其由Doug Lea从1987年开始编写,到目前为止,最新版本为2.8.3,由于其高效率等特点被广泛的使用。U-boot上使用的dlmalloc的版本是 2.6.6。Android bionic C库也使用, 实现C库的malloc分配.android里, 源码位置bionic/libc/upstream-dlmalloc/malloc.c uboot里源码 common/dlmalloc.c.
chunk "块", 实际上指带一块内存, 包括了管理信息.
bins "箱柜", dlmalloc算法中, 用于快速定位所需要的chunk
#define top (bin_at(0)->fd) /* The topmost chunk */ 特殊的bin, 指向内存最顶端的chunk
#define last_remainder (bin_at(1)) /* remainder from last split */ 特殊的bin, 指向最近分配的chunk剩下的chunk.
sbrk "系统调用" 用来移动用户空间看见的heap的边界
CALL_MORECORE 实际上是不同平台的操作系统分配调用的实现, linux上是brk.b
2. 算法逻辑
(1) chunk管理
有两种类型的chunk,已分配的chunk和未分配的chunk,两者交错排列,占据了整个heap空间。注意,没有相邻的两个未分配的 chunk,因 为在调用free释放被使用过的chunk时,dlmalloc将合并任何相邻的空闲chunk。交错的两种chunk看起来是这样的。
(2) Top chunk
Top最初被称为wilderness chunk,指向dlmalloc 可用内存的最高端的边界chunk,因为在边界上,top是唯一一个可以任意扩展的块。Top比较特殊,它不受任何分 箱管理,当其他分箱没有可用的chunk时才会用到top。在dlmalloc初始化刚完成时,整个受dlmalloc管理的内存就是一个 chunk,top即指向这个chunk。
(3) Last_remainder chunk
Last_remainder 总是指向最近被分割chunk的剩下那一部分。 如果malloc在分配时没有找到“精确匹配”的块,则优先去查看last_remainder是否够用。从局部性原理来讲,连续申请分配内存的代码总是 趋向于有共同的生命周期,它们释放的chunk也就有很大的机会合并成一个大的chunk。
(1) 在smapllbin里查找, 这个查找很快, 有就返回
(2) 在tree bin里查找, 这个查找稍慢, 有就返回
(3) 在大的块链里顺序查找, 这个最慢, 有就返回
(4) 查看top chunk, 可以分的话, 就分解top chunk
(5) sys_alloc, sys_alloc里linux用的是brk系统调用.
mem = sys_alloc(gm, nb);, gm是全局的 static struct malloc_state _gm_, 管理这整个malloc状态.
sys_alloc里, 包含了初始化工作, 如果是第一次分配, 就会初始化一下, 同时把分配到内存块赋值给top, 再从top分配用户需要的大小.init_top接口用于初始化top.
(6) free释放时候, 会合并相邻的chunk, 同时适当情况下, 调用brk, 让内核释放页面.