博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ptmalloc内存分配释放
阅读量:5067 次
发布时间:2019-06-12

本文共 3133 字,大约阅读时间需要 10 分钟。

 

分配:

1)获取分配区的锁,为了防止多个线程同时访问同一个分配区,在进行分配之前需要取得分配区域的锁。线程先查看线程私有实例中是否已经存在一个分配区,如果存在尝试对该分配区加锁,如果加锁成功,使用该分配区分配内存,否则,该线程搜索分配区循环链表试图获得一个空闲(没有加锁)的分配区。如果所有的分配区都已经加锁,那么ptmalloc会开辟一个新的分配区,把该分配区加入到全局分配区循环链表和线程的私有实例中并加锁,然后使用该分配区进行分配操作。开辟出来的新分配区一定为非主分配区,因为主分配区是从父进程那里继承来的。开辟非主分配区时会调用mmap()创建一个sub-heap,并设置好top chunk。

2)将用户的请求大小转换为实际需要分配的chunk空间大小。
3)判断所需分配chunk的大小是否满足chunk_size <= max_fast (max_fast 默认为64B),如果是的话,则转下一步,否则跳到第5步。
4)首先尝试在fastbins中取一个所需大小的chunk分配给用户。如果可以找到,则分配结束。否则转到下一步。
5)判断所需大小是否处在smallbins中,即判断chunk_size <512B是否成立。如果chunk大小处在smallbins中,则转下一步,否则转到第6步。
6)根据所需分配的chunk的大小,找到具体所在的某个small bin,从该bin的尾部摘取一个恰好满足大小的chunk。若成功,则分配结束,否则,转到下一步。
7)到了这一步,说明需要分配的是一块大的内存,或者small bins中找不到合适的chunk。于是,ptmalloc首先会遍历fastbins中的chunk,将相邻的chunk进行合并,并链接到unsorted bin中,然后遍历unsorted bin中的chunk,如果unsorted bin只有一个chunk,并且这个chunk在上次分配时被使用过,并且所需分配的chunk大小属于small bins,并且chunk的大小大于等于需要分配的大小,这种情况下就直接将该chunk进行切割,分配结束,否则将根据chunk的空间大小将其放入small bins或是largebins中,遍历完成后,转入下一步。
8)到了这一步,说明需要分配的是一块大的内存,或者small bins和unsorted  bin中都找不到合适的chunk,并且fastbins和unsorted bin中所有的chunk都清除干净了。从large bins中按照“smallest-first,best-fit”原则,找一个合适的chunk,从中划分一块所需大小的chunk,并将剩下的部分链接回到bins中。若操作成功,则分配结束,否则转到下一步。
9)如果搜索fastbins和bins都没有找到合适的chunk,那么就需要操作top  chunk来进行分配了。判断top  chunk大小是否满足所需chunk的大小,如果是,则从top chunk中分出一块来。否则转到下一步。
10)到了这一步,说明top chunk也不能满足分配要求,所以,于是就有了两个选择: 如果是主分配区,调用sbrk(),增加top chunk大小;如果是非主分配区,调用mmap来分配一个新的sub-heap,增加top chunk大小;或者使用mmap()来直接分配。在这里,需要依靠chunk的大小来决定到底使用哪种方法。判断所需分配的chunk大小是否大于等于mmap分配阈值,如果是的话,则转下一步,调用mmap分配,否则跳到第12步,增加top chunk 的大小。
11)使用mmap系统调用为程序的内存空间映射一块chunk_size align 4kB大小的空间。然后将内存指针返回给用户。
12)判断是否为第一次调用malloc,若是主分配区,则需要进行一次初始化工作,分配一块大小为(chunk_size  +  128KB)  align  4KB大小的空间作为初始的heap。若已经初始化过了,主分配区则调用sbrk()增加heap空间,分主分配区则在top chunk中切割出一个chunk,使之满足分配需求,并将内存指针返回给用户

 

释放:

1)free()函数同样首先需要获取分配区的锁,来保证线程安全。

2)判断传入的指针是否为0,如果为0,则什么都不做,直接return。否则转下一步。
3)判断所需释放的chunk是否为mmaped  chunk,如果是,则调用munmap()释放mmaped  chunk,解除内存空间映射,该该空间不再有效。如果开启了mmap分配阈值的动态调整机制,并且当前回收的chunk大小大于mmap分配阈值,将mmap分配阈值设置为该chunk的大小,将mmap收缩阈值设定为mmap分配阈值的2倍,释放完成,否则跳到下一步。
4)判断chunk的大小和所处的位置,若chunk_size <= max_fast,并且chunk并不位于heap的顶部,也就是说并不与top  chunk相邻,则转到下一步,否则跳到第6步。(因为与topchunk相邻的小chunk也和top  chunk进行合并,所以这里不仅需要判断大小,还需要判断相邻情况)
5)将chunk放到fastbins中,chunk放入到fastbins中时,并不修改该chunk使用状态位P。也不与相邻的chunk进行合并。只是放进去,如此而已。这一步做完之后释放便结束了,程序从free()函数中返回。
6)判断前一个chunk是否处在使用中,如果前一个块也是空闲块,则合并。并转下一步。
7)判断当前释放chunk的下一个块是否为top  chunk,如果是,则转第9步,否则转下一步。
8)判断下一个chunk是否处在使用中,如果下一个chunk也是空闲的,则合并,并将合并后的chunk放到unsorted  bin中。注意,这里在合并的过程中,要更新chunk的大小,以反映合并后的chunk的大小。并转到第10步。
9)如果执行到这一步,说明释放了一个与top chunk相邻的chunk。则无论它有多大,都将它与top chunk合并,并更新top chunk的大小等信息。转下一步。
10)判断合并后的chunk 的大小是否大于FASTBIN_CONSOLIDATION_THRESHOLD(默认64KB),如果是的话,则会触发进行fastbins的合并操作,fastbins中的chunk将被遍历,并与相邻的空闲chunk进行合并,合并后的chunk会被放到unsorted bin中。fastbins将变为空,操作完成之后转下一步。
11)判断top chunk的大小是否大于mmap收缩阈值(默认为128KB),如果是的话,对于主分配区,则会试图归还top  chunk中的一部分给操作系统。但是最先分配的128KB空间是不会归还的,ptmalloc 会一直管理这部分内存,用于响应用户的分配请求;如果为非主分配区,会进行sub-heap收缩,将top chunk的一部分返回给操作系统,如果top chunk为整个sub-heap,会把整个sub-heap还回给操作系统。做完这一步之后,释放结束,从free()函数退出。可以看出,收缩堆的条件是当前free的chunk大小加上前后能合并chunk的大小大于64k,并且要top  chunk的大小要达到mmap收缩阈值,才有可能收缩堆。

转载于:https://www.cnblogs.com/snip3r/p/10578926.html

你可能感兴趣的文章
React组件属性类型(propTypes)
查看>>
js 过滤script
查看>>
uwsgi xml 配置
查看>>
UIView
查看>>
吴裕雄 python 神经网络——TensorFlow实现AlexNet模型处理手写数字识别MNIST数据集...
查看>>
LUA 拾遗(编译-调试-运行)
查看>>
loj10200. 「一本通 6.2 练习 3」Goldbach's Conjecture
查看>>
R-CNN(Rich feature hierarchies for accurate object detection and semantic segmentation)论文理解...
查看>>
.net IDE 界面编程AutoScale属性惹的大麻烦
查看>>
Kolor Panotour Pro 使用方法
查看>>
面向对象第四单元小结
查看>>
关于手思3.0 代码规范
查看>>
关于注册登陆时候进行的归档解档--严焕培
查看>>
shell 数组操作
查看>>
POJ 3723 - Conscription ( 最大权森林 / 最小生成树 )
查看>>
用maven搭建 testNG+PowerMock+Mockito测试框架
查看>>
Streams全库复制
查看>>
MYSQL数据库导入出错:#1046 - No database selected
查看>>
JavaSE聊天室
查看>>
2017.8.30 elasticsearch-sql的安装与使用
查看>>