【Linux内存泄漏专题】如何分析Linux内存泄漏问题?

一、内存泄漏定义

        在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。

二、内存泄漏分类

2.1、根据泄漏发生方式分类

        2.1.1、常发性泄漏

                故障代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

        2.1.2、偶发性泄漏

                故障代码只有在特定场景或操作过程下才会被执行,注意,常发性和偶发性是相对的,对于特定场景,偶发性也许就变成了常发性的,所以测试场景和方法对检测内存泄漏至关重要。

        2.1.3、一次性泄漏

                故障代码只会被执行一次或者由于逻辑的缺陷导致只有一块内存发生泄漏。

        2.1.4、隐式泄漏

                程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存,严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存,但对于daemon或需要长时间运行的程序来讲,不及时释放可能最终耗尽所有内存。

2.2、根据泄漏类型分类

        2.2.1、未引用泄漏

                这些泄漏点,已无任何指针指向,因此无法被找到,永远无法被释放。

        2.2.2、引用泄漏

                这些泄漏点可以被找到,等于隐式泄漏,引用泄漏像是缓存没有控制上限而导致耗尽内存,如果控制的好,则没问题,比如Kernel里的 slub 也有 percpu 缓存。

三、/proc/meminfo文件解读

        /proc/meminfo 文件对于 Linux 内存泄漏问题的分析至关重要,因此,对该文件中参数的熟悉程度也决定了对内存泄漏问题的分析效率,下面来看看这些参数的含义。

四、Linux系统内存监控项

        关于系统内存信息的监控,一般来说是通过轮询,周期性的查看memory的使用情况,监测的数据一般包括:

4.1、/proc/meminfo

        系统内存使用情况,这是内存问题分析中最重要的文件,通过该文件可以初步判定可能内存消耗异常点。

4.2、ps -l

        打印系统所有进程 / 线程内存情况,可观察每个进程的线程量、VSS/RSS等。

        在评估一个进程的内存使用时,我们往往需要观察它使用的虚拟内存空间,物理内存空间以及它和其他进程有均摊多少内存等,即:

                1)VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)

                2)RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)

                3)PSS - Proportional Set Size 实际使用物理内存(比例分配共享库占用的内存)

                4)USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

4.3、df -Th

        打印系统挂载的文件系统使用情况。

4.4、/proc/slabinfo

        slub 的内存使用情况,需要在内核开启相关宏。

4.5、/sys/kernel/debug/page_owner

        page owner主要用于查看内核中内存页的使用情况,它一般用于内存黑洞或者kmalloc-4k及以上的内存泄漏问题的分析。

        这里应该有人有疑问了,什么是内存黑洞呢?我们所说的内存黑洞指的是不能被Linux内核监控到的内存,一般来说是直接调用__alloc_pages函数申请的内存,换句话说,只要我们发现meminfo中除了MemAvailble/MemFree一直在减少,而其他模块的内存并无异常时,我们就认为内存泄漏发生在内存黑洞中,内存黑洞内存泄漏问题需要借助page owner工具来分析,这部分后面会介绍。

       下面是对内存泄漏问题复测过程中需要重点监控的信息,需要注意的是,在获取内存数据前需要先清掉 buffer/cache,避免对后续分析造成影响

# echo 3 > /proc/sys/vm/drop_caches                                      # 必选项,查询内存前需要先清cache,避免对后续分析造成影响
# cat /proc/meminfo
# ps -l
# df -Th
# cat /proc/slabinfo > /data/slabinfo                                    # [可选] 打开slabinfo且初步定位slab模块内存泄漏
# cat /sys/kernel/debug/page_owner > /data/page_owner_full_before.txt    # [可选] 打开page owner且初步定位到内存黑洞内存泄漏

五、Linux内存泄漏问题分析流程

        Linux内存泄漏问题的排查相对比较复杂和繁琐,在稳定复现的环境的情况下,最少也要复测2-3次才能定位泄漏点,而找到泄漏点只是第一步,对于泄漏点的修复也并不容易,这里面涉及到很多内核模块的知识点,所以,对内核的熟悉程度也决定了问题的处理效率,平时工作中处理的内存泄漏问题的周期普遍都较长,这个需要在实战中磨炼慢慢练成"火眼金睛"。

        下图是笔者对平时工作处理的内存泄漏问题分析流程的总结梳理,通过这个分析流程,可以快速定位到内存泄漏点,然后进一步分析出现泄漏的原因。

        结合平时工作中遇到的内存泄漏问题的分析,系统中有部分内存是在系统启动后使用增加,但是到达最大限制后就不会增加,比如之前遇到过的系统log进程内存消耗,只在系统启动后开始申请内存使用,但是它有一个内存大小使用的限制,还有就是部分驱动中也有类似的情况,这些内存的使用会对问题的分析产生影响,所以,一般来说,不太建议复现内存泄漏问题时只抓取before和after的信息,建议在加上一次middle,这样对问题分析很有帮助。

        上图从大体上介绍了内存泄漏问题的分析流程,至于内存泄漏点的定位,不同场景的处理方式也不相同,比如进程的内存泄漏点可以使用Valgrind工具检测,内核泄漏点可以通过page onwer工具、kmemleak或者自定义的slabtrace工具来定位,这些工具的使用和分析会在下一章节中一一介绍,敬请期待。

  • 16
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值