malloc是如何分配内存的?

一、malloc介绍

malloc库函数:用来动态分配内存

malloc()分配的是虚拟内存,只有当访问到这块虚拟内存时,操作系统才会查询页表,发现虚拟内存对应的也没有在物理内存中,就会引发缺页中断,然后建立起虚拟内存页与物理内存页之间的映射关系。

二、malloc申请内存时的两种方式

1、通过brk()系统调用在堆区分配内存

如果用户分配的内存小于128KB,通过brk()函数将堆顶指针向高地址移动,获得新的内存空间。当free()之后,堆区内存还在,并没有归还给操作系统,而是缓存在了内存池中供下次使用,这样速度快了很多,因为已经建立起了虚拟内存与物理内存的映射关系,不会再产生缺页中断了。

2、通过mmap()系统调用在文件映射区分配内存

如果用户分配的内存大于128KB,通过mmap()系统调用在文件映射区分配一块内存。当free()之后,会把内存归还给操作系统,此时内存得到了真正的释放。

三、为什么不全使用mmap来分配堆区内存?

1、mmap是系统调用,每次执行时都会发生用户态和内核态的切换。

2、mmap分配的内存每次释放的时候,都会把内存归还给操作系统,这样每次mmap分配的虚拟地址都是缺页状态,然后在第一次访问虚拟地址时就会发生缺页中断,这样会导致CPU消耗较大。

相比于brk:

调用free时并没有释放堆区内存,只是把它放到了内存池里,并且虚拟内存与物理内存的映射关系还在,那么下次再申请内存的时候,直接从内存池里取出相应的内存块就行了,这样不仅减少了系统调用的次数,也减少了缺页中断的次数,大大降低了CPU的消耗。

四、为什么不全使用brk来分配堆区内存?

场景一:用户连续申请了10K,20K,30K三块内存,如果10K,20K这两块内存释放了,如果下次申请的内存小于30K,就可以重用这个空闲内存空间。日过申请的内存大于30K,那么brk指针还得上移,实际使用的内存继续增大。

因此,随着不断的malloc和free,对于小块内存,堆内会产生越来越多的内存碎片。

所以,规定用户申请的内存小于128KB时使用brk,大于128KB时使用mmap。

五、free()函数只是传入了一个地址,为什么能够知道要释放多大的内存?

malloc返回给用户态的起始内存地址比进程的堆空间起始地址多了16个字节,这个多出来的16个字节就是保存了该内存块的信息,当调用free的时候,free会对传入进来的内存地址向左便宜16个字节,然后从这16个字节中分析出当前的内存块大小,自然就知道要释放多大的内存了。

补充:

显示进程号为pid的内存使用情况

cat /proc/pid/maps
pmap -d pid

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值