ptmalloc内存分配释放
分配:
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收缩阈值,才有可能收缩堆。
ptmalloc内存分配释放的更多相关文章
- delphi 精要-读书笔记(内存分配释放)
delphi 精要-读书笔记(内存分配释放) 1.内存分为三个区域:全局变量区,栈区,堆区 全局变量区:专门存放全局变量 栈区:分配在栈上的变量可被栈管理器自动释放 堆区:堆上的变量内存必须人 ...
- delphi.memory.分配及释放---New/Dispose, GetMem/FreeMem及其它函数的区别与相同,内存分配函数
来自:http://www.cnblogs.com/qiusl/p/4028437.html?utm_source=tuicool&utm_medium=referral ---------- ...
- c++内存分配
[导语] 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不 ...
- openssl内存分配,查看内存泄露
openssl内存分配 用户在使用内存时,容易犯的错误就是内存泄露.当用户调用内存分配和释放函数时,查找内存泄露比较麻烦.openssl提供了内置的内存分配/释放函数.如果用户完全调用openssl的 ...
- ptmalloc,tcmalloc和jemalloc内存分配策略研究 ? I'm OWen..
转摘于http://www.360doc.com/content/13/0915/09/8363527_314549949.shtml 最近看了glibc的ptmaoolc,Goolge的tcmall ...
- C语言中的内存分配与释放
C语言中的内存分配与释放 对C语言一直都是抱着学习的态度,很多都不懂,今天突然被问道C语言的内存分配问题,说了一些自己知道的,但感觉回答的并不完善,所以才有这篇笔记,总结一下C语言中内存分配的主要内容 ...
- DLL函数中内存分配及释放的问题
DLL函数中内存分配及释放的问题 最近一直在写DLL,遇到了一些比较难缠的问题,不过目前基本都解决了.主要是一些内存分配引起问题,既有大家经常遇到的现象也有特殊的 情况,这里总结一下,做为资料. 错误 ...
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
http://blog.csdn.net/pi9nc/article/details/23334659 注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料 ...
- 动态内存分配(new)和释放(delete)
在之前我们所写过的程序中,所必需的内存空间的大小都是在程序执行之前就已经确定了.但如果我们需要内存大小为一个变量,其数值只有在程序运行时 (runtime)才能确定,例如有些情况下我们需要根据用户输入 ...
随机推荐
- 深度学习识别CIFAR10:pytorch训练LeNet、AlexNet、VGG19实现及比较(二)
版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com AlexNet在2012年ImageNet图像分类任务竞赛中获得冠军.网络结构如下图所示: 对CIFA ...
- 基于 docker 的yapi(快速部署)
1.使用官方的mongodb镜像 docker run --network yapi_net --ip 172.30.0.10 -d --name yapi_mongodb --restart al ...
- 快速实现兼容的js复制方式。有点非正规,通过非正规的排版实现。
<div style="height:1px; width:1px; overflow:hidden; position:absolute;left:-2px;"> & ...
- StringBuilder的常用方法
转自:https://www.cnblogs.com/jack-Leo/p/6684447.html 在程序开发过程中,我们常常碰到字符串连接的情况,方便和直接的方式是通过"+"符 ...
- docker容器启动haproxy
1.在本地新增haproxy.cfg文件(本次haproxy.cfg文件路径为/root/haproxy.cfg),内容如下: #---------------- # Global settings ...
- Filebeat 日志收集器 安装和配置
Filebeat的配置文件是/etc/filebeat/filebeat.yml,遵循YAML语法.具体可以配置如下几个项目: Filebeat Output Shipper Logging(可选) ...
- mybatis 插入 含有美元符号($) 字符串 报 java.lang.IndexOutOfBoundsException: No group 2 的问题
一:问题描述: 在springboot-security框架生成BCryptPasswordEncoder()方法生成加密后的密码后,带有$符号,导致新增用户的时候插入不了,报(IndexOutOfB ...
- Educational Codeforces Round 63 (Rated for Div. 2)
传送门 A. Reverse a Substring 题意: 给你一串 s,让你判断能否通过反转区间[l,r]的元素,使得反转后的串的字典序小于 s: 如果能,输出 "YES",并 ...
- java强引用 软引用 弱引用 虚引用
https://www.cnblogs.com/yw-ah/p/5830458.html Java四种引用包括强引用,软引用,弱引用,虚引用. 强引用: 只要引用存在,垃圾回收器永远不会回收Objec ...
- Java基础--面向对象编程4(多态)
1.多态的概念 多态是指程序中的同一引用类型,使用不同的实例而执行结果不同的. 同一个类型:一般指父类 不同的实例:不同的子类实例 执行结果不同:针对同一方法执行的结果不同 package cn.sx ...