malloc与free

glibc的alloctor--ptmalloc

ptmalloc这个内存分配器实现了malloc()和free()等函数,ptmalloc把各个不同大小的内存块以chunk这样的数据结构的形式用双向链表串起来,一个链表就是一个bin,ptmalloc共有128个bin,分为fast bins 、unsorted bins、small bins 、large bins ,当用户通过malloc申请内存的时候,如果第一次申请的内存小于128kb,ptmalloc就会申请一个128kb大小的空间初始化heap,如果第一次大于128kb就直接调用mmap()函数映射一块用户所需大小的内存,用完直接归还给os.
为了支持多线程,ptmalloc分了主分配区和非主分配区 ,主分配区可以调用brk(),mmap(),但非主分配区只能调用mmap(),线程申请内存时都要对分配区加锁,如果所有的分配区都加锁了,就该线程就自己开一个非主分配区加入环形链表中

malloc()

1、申请分配区的锁
2、将用户申请的大小转化为chunk大小
3、如果chunk_size<max_fast就在fast_bins中分配一块出去,如果分配不成功就下一步
4、在small bins 中找一个合适的大小从链表尾部删除(插入的时候头插)
5、如果small bins中没有找到,就把fast bins 中的chunk合并加入unsorted bins 做适当的切割之后将剩余的加入small bins 或者large bins ,如果unsorted bins 没有分配成功就将其插入large bins 中,此时fast bins 和unsorted bins 已经为空
6、在large bins中查找chunk分配给用户,按照最合适的chunk分配,前面都是精确匹配,这里选择最适应的大小分配
7、如果第6步还没有分配成功就从top chunk中分配(top chunk为heap的最顶端),如果top chunk大小不够,若是主分配区就调用sbk()增加top chunk的大小,若还是分配不成功就调用mmap()函数直接映射,而非主分配区若top chunk分配不成功,就不增加top chunk大小,直接调用mmap()映射

free()

1、获取分配区的锁
2、判断是否为mmap chunk,如果是就调用munmap()释放返回给os,如果chunk大于mmap()阈值并且开启了阈值动态调整机制就将阈值设为当前chunk值,并且将收缩阈值设为当前chunk的二倍
3、判断chunk_size<max_fast,如果是就放入fast bins中,并且不修改状态为P,如果大于就加入unsorted bins合并,并跳到第六步,如果小于并且与top chunk 相邻就加入top chunk,跳到第7步
4、看chunk后面是否为空闲chunk,是的话就合并加入unsorted bins 
5、如果合并后的chunk大于 64kb就遍历fast bins 合并所有chunk,加入unsorted bins ,此时fast bins 就是为空了
6、判断合并后的chunk是否和top chunk相邻,相邻就加入top chunk 
7、如果top chunk的值大于mmap()分配阈值就将一部分返回给os,留128kb(初始化后的大小)

总结:收缩堆的条件是:当合并后的chunk大于64kb并且top chunk的值大于收缩阈值时

猜你喜欢

转载自blog.csdn.net/crazy_to_imagine/article/details/75195150