glibc大量小内存的释放

本文探讨了Linux环境下内存管理的问题,特别是当内存因异常情况飙升后无法有效释放的情况。文章指出,小内存分配主要通过brk,大内存通过mmap,释放内存时,brk分配的内存可能不会立即归还操作系统。通过调整glibc的M_MMAP_THRESHOLD和M_TRIM_THRESHOLD参数,可以影响内存分配和释放策略,但可能影响性能。malloc_trim(0)函数用于尝试释放堆顶内存,能在一定程度上解决内存空洞问题,适合在特定场景下使用。最后,建议根据业务需求平衡性能和内存管理。

之前在项目中,发现内存在某些情况下飙升,然后无法降下来的情况,记录一下解决过程。

大概情况就是:程序在运行中需要不停申请小块内存用来接收传输过来的视频数据,将数据保存到磁盘后然后释放掉free掉,正常情况下,总的占用内存维持在一个合理的水平,但是如果磁盘出现写入性能下降的情况时,造成接收的数据堆积,此时需要去申请更多的内存来缓存数据,此时进程总的占用内存变显著增大,这种情况也是可接受的。如果接下来磁盘写入性能恢复正常,缓存的数据减少,大部分申请的内存释放,此时进程占用的总内存应该恢复到正常水平。但是问题来了,在项目中发现,如果进程使用内存一旦因为异常情况升高,内存几乎是再也降不下来了。

开始怀疑是程序内存泄漏,在使用各种方法定位后排除了程序本身内存泄漏的可能,而且确认是调用了free释放掉了内存,那free后的内存为何没有归还给操作系统?

经过查资料,得知Linux下内存管理是由glic库来与内核交互,即用户空间是通过glic来进行的系统调用。glic提供两种方式来申请内存,分别是brk和mmap,当通过malloc/new申请的内存小于M_MMAP_THRESHOLD(缺省128K)时,glic调用brk来申请内存,当要申请的内存大于M_MMAP_THRESHOLD时,glic调用mmap来申请内存。这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。 

brk是将数据段(.data)的最高地址指针_edata往高地址推,完成虚拟内存分配;而通过mmap系统调用分配的内存是在堆和栈的中间空闲地址分配一块虚拟内存,这样释放时可以不受约束地自由释放。这样通过brk分配的内存是连续的一块空间,如下图中依次brk申请ABD内存,释放的时候,若高地址的内存不释放,低地址的内存是不能释放的,如下图(7);而mmap申请的内存可以自由释放,如下图(6)。

评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值