【问题记录】kmemleak 定位内存泄露

本文介绍了在项目开发中遇到内存逐渐减少的问题,通过分析可能的原因如内存泄露和系统缓存。重点讲解了如何使用kmemleak工具进行内存泄露检测,包括配置内核、挂载debugfs以及解读输出信息。通过实际案例展示了kmemleak在定位内存泄露代码中的应用。
摘要由CSDN通过智能技术生成

一、内存泄露问题

在项目开发过程,有时候通过 free 命令发现可用内存在逐渐减少,但是通过 top 或者 pidstat -r 等工具看不到异常占用内存进程的情况,可能存在以下原因:

  1. 内存泄漏。一些内存使用方式会导致系统逐渐耗尽内存,这种情况下内存可能是在内核 space 中占用。
  2. 系统缓存。系统会将一些文件和数据缓存到可用内存中,如果一段时间内没有被使用,缓存的内容就会逐渐增加。这种情况下,通过 free 命令可以看到使用缓存时 available 数值降低的情况。即使没有进程明显占用内存,系统也可能运行缓慢。

二、判断内存是否泄露

  1. 通过 free、cat /proc/meminfo 查看可用内存是否逐渐减少
    在这里插入图片描述
    【结果分析】平均每小时内存减少 21MB。
  2. 通过 cat /proc/slabinfo 确认内存减少的对象
    在这里插入图片描述
    【结果分析】减少最多的是 kmalloc-1024,内存存在泄露。

三、使用KMEM来定位内存泄露代码

1. kmemleak

kmemleak 是 Linux 内核用于检测内存泄露的一种工具,实现的基本原理是通过对 kmalloc()、vmalloc()、kmem_cache_alloc() 等内存分配接口,跟踪其分配的指针、分配内存大小、堆栈等跟踪信息,存储在 kmemleak 数据结构中。

2. 内核配置

+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=20000  // 这个值应设置较大,不然会有下面的问题
+# CONFIG_DEBUG_KMEMLEAK_TEST is not set

在启动阶段,由于默认 CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE 配置过小,系统启动阶段 early log 溢出,会导致 kmemleak 被自动禁用,log 如下:

[    0.000000] kmemleak: Kernel memory leak detector disabled
[    0.000000] clk r_dsp_cache0 not found in of_sunxi_periph_cpus_clk_setup
[    0.000000] clk r_dsp_cache1 not found in of_sunxi_periph_cpus_clk_setup
[    0.000000] clocksource: timer: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 79635851949 ns
[    0.000000] arm_arch_timer: Architected cp15 timer(s) running at 24.00MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x588fe9dc0, max_idle_ns: 440795202592 ns
[    0.000005] sched_clock: 56 bits at 24MHz, resolution 41ns, wraps every 4398046511097ns
[    0.008203] Console: colour dummy device 80x25
[    0.012434] kmemleak: Early log buffer exceeded (1438), please increase DEBUG_KMEMLEAK_EARLY_LOG_SIZE

3. 使用方式

1、挂载debugfs
    mount -t debugfs nodev /sys/kernel/debug/
2、内核线程每10分钟(默认情况下)扫描一次,并打印找到的可疑的内存泄漏object。也可以在任意时刻执行kmemleak的内存扫描。
    echo scan > /sys/kernel/debug/kmemleak
3、详细的输出信息通过/sys/kernel/debug/kmemleak获取。
    cat /sys/kernel/debug/kmemleak

四、应用现场

在这里插入图片描述
【结果分析】可以看到是在e1mcc_pppd 进程在系统调用时,对tty 操作中调用了 alloc_tty_struct 函数里面去申请的内存,但是这段内存并没有释放掉,所以造成了内存泄露。


五、总结

在某些复杂的项目中,如果存在内存泄露问题,而又无法通过常规的命令工具去定位问题,若通过代码去逐步排查也很难去排查出来,通过kmemleak工具就可以很好的帮我们定位出来内存泄露的具体代码处,进而缩小问题的范围。比如上面的示例中,定位出来是 tty_open 函数内申请的内存,那对应的应该想到是不是在tty_close或者对应的退出函数中该段内存没有去释放掉,可以通过添加打印来逐步排查。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值