内存申请(malloc)和释放(free)之下篇

上篇介绍了内存malloc的sbrk和brk系统调用,以及mmap函数。本篇开始学习下内存的具体的malloc分配逻辑和free逻辑。(本篇幅的学习借助,华庭大神(阿里 庄明强) 总结的ptmalloc源码资料)

 

1.简介

linux系统glibc库是linux系统中最底层的c语言运行库,glibc库中分配内存和释放内存使用的函数是ptmalloc函数和free函数,分配器处在用户程序和内核之间,响应用户的内存分配请求。为了高效分配,分配器一般会预先分配一块大于用户请求的内存,并通过某些算法来管理这块内存,来满足用户的内存申请,当然 用户free内存的时候,也不是立即归还给OS操作系统,也是分配器通过一些算法管理这些空闲的内存,以便于下次申请内存,直接复用,提高内存的使用效率。

2.ptmalloc设计假设

Ptmalloc在设计时候折中效率,高空间利用率、高可用设计目标,其设计代码中存在内存管理的一些假设:

(1).具有长生命周期的或者特大块内存分配,采用mmap方法,主要是mmap映射匿名页面,当发生缺页中断时,linux内核会缺页分分配一个新的物理页面,并将改物理页面清0,一个mmap需要多个页面映射,导致多次清0操作,浪费系统资源。故引入动态阈值调整机制,分配的内存大于一定值,才使用mmap函数申请内存。

(2).具有短生命周期、内存大小较小的内存使用brk分配

(3).尽量只缓存临时使用的空闲小内存块,对大内存块或是长生命周期的大内存块在释放时都直接归还给操作系统。

(4).对空闲小内存块只会在malloc和free时候才进行合并,free空闲的内存块可能放入pool中,不一定还给操作系统

(5).收缩堆的条件是 当前free的内存块大小加上前后合并的chunk内存大小大于64kB(32位系统),并且堆顶的大小达到阈值,才能收缩堆,把堆最顶端的空闲的内存返回给操作系统

(6).内存碎片产生:多线程可以从同一个分配区中分配内存,线程A释放一块内存后,线程B会申请内存,大小和A申请的大小不一样,或许是一个小的差别。就需要对内存块进行不停的分割和合并操作,这个过程可能会存在内存碎片

下面结合几个图来理解下:

第一步:开辟内存,A=40k, B= 50k,D= 60K,C=128K,由于C=128K 大于mmap默认大小,故使用mmap开辟内存

 

 

第二步: 如上右图所示,malloc(E) 且 E= 100k 小于128K,故使用brk分配内存,移动brk指针,从堆空间中分配内存。

第三部:释放A空间,free(A),接着开辟30k内存,malloc(30k)

free(A)后,A的内存块不会立马归还给操作系统,此时给A内存块打上标记,表示改内存处于空闲状态。此时如果系统再次分配30k的内存时,查询到有40k的内存块处于空闲状态,会把40K内存分割成30K和10K,重用30k内存大小,剩余的10K 暂且会搁置。后面如果不能合并,也不能被重用,就会形成内存碎片

第四步:free(C), C= 128k, free(D) D=60K

由于C=128K,free(C) 会调用mummap()直接释放内存块,归还给操作系统。free(D),D=60K,此时由于D和A=40k内存,地址空间不连续,故不能合并,会存在由上图情况,存在两块空闲内存。

第五步: free(E)  E=100k

free(E),E=100k,如上左图 E=100k 和60k地址连续,会合并形成160K大小的内存,大于默认值(128K),且内存靠近堆顶指针,sbrk回溯,此时内存归还给os操作系统

未完待续。。。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值