记录一次kernel内存泄漏的查找定位过程

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/voidreturn/article/details/72357242 Bug描述...
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/voidreturn/article/details/72357242

Bug描述:压力测试一个小工程时发现内存逐渐减少,10个小时后出现OOM

Bug定位过程:

  • 对整个工程模块进行分解,逐步缩小范围,由于整个工程包括几个相对独立的小模块,而整个工程采用单进程多线程的模型,导致进行分解时,要特别注意相互之间的耦合,只能逐步分离各个模块,运行测试(这里如果采用多进程模型,定位会更快一些,一个完整的功能,放在一个进程和多进程中,多进程天然的将功能细化了,定位问题,范围更小)
  • 在经过一段折磨人的拆分过程后,最后把问题定位到整个工程中一个小模块功能内。在对该模块进行了反复的代码review后,没有发现什么异常,甚至没有内存申请的操作。
  • 代码层面没有找到突破的情况下,重新通过各种命令查看了内存状态,由于在此之前一直通过free命令查看内存,发现长时间后free命令输出的可用内存在逐渐减少,但忽略了一点:通过top命令单独查看模块进程占用的内存时,该进程的rss段一直保持稳定,没有大幅度增长。
  • 基于前一步的发现,怀疑是kernel的内存有泄漏,查看/proc/meminfo发现一个疑点:slab内存占用很高,且SUnreclaim的slab一直在增加,此时基本确定kernel内存泄漏。
  • 通过kmemleak对内核内存进行了分析,定位在到一个函数接口中:
char *wr_pr_debug_begin(u8 const *data, u32 len, char *string)
{
    int ii;
    string = kmalloc(len * 2 + 1, GFP_KERNEL);
    for (ii = 0; ii < len; ii++)
        sprintf(&string[ii * 2], "%02X", data[ii]);
    string[len * 2] = 0;
    return string;
}
char *wr_pr_debug_end(char *string)
{
    kfree(string);
    return "";
}
void test()
{
    char *read = 0;
    pr_debug("%s RD%02X%02X%02X -> %s%s\n", st->hw->name,
         i2c_addr, reg, length,
         wr_pr_debug_begin(data, length, read),
         wr_pr_debug_end(read));
}

一眼可能不容易看出上面的有什么问题,有kmalloc,有kfree啊,好像成对出现的。
考验基本功的时候到了,熟悉函数调用传参的人应该会知道编译器一般对参数的处理采用堆栈的方式,是一个先进后出的过程,这样参数的执行一般是逆序的(由于编译器实现的不同,这个过程不是确定的),这样kfree会在kmalloc之前运行,导致每次运行都会泄漏一点内存。上面是一个debug输出,暂时注释掉后压测,问题解决,内存保持稳定。

总结:整个定位过程其实比较简单,如果第一步看下/proc/meminfo可能会更快的定位问题(由于这个kernel driver是“大厂”提供,以为不会出问题,一直从上层的角度去找问题,所以没有太关注kernel相关内存的使用),导致内存泄漏的原因也很简单,出现这种问题的原因,首先编写者的基本功一般,更主要的原因是编写者出于“炫技”的方式去写了这段代码,如果老老实实封装一个debug函数,按照正常顺序调用也就没有问题了,而且这种每次打印进行kmalloc的方式,对性能也是有些影响的。总之基本功还是很重要,而且不要驾驭自己驾驭不了的编码方式。

目录
相关文章
|
Arthas 运维 监控
定位频繁创建对象导致内存溢出风险的思路
定位频繁创建对象导致内存溢出风险的思路
312 1
|
2月前
|
监控 JavaScript 算法
如何使用内存监控工具来定位和解决Node.js应用中的性能问题?
总之,利用内存监控工具结合代码分析和业务理解,能够逐步定位和解决 Node.js 应用中的性能问题,提高应用的运行效率和稳定性。需要耐心和细致地进行排查和优化,不断提升应用的性能表现。
195 77
|
6月前
|
存储 设计模式 监控
运用Unity Profiler定位内存泄漏并实施对象池管理优化内存使用
【7月更文第10天】在Unity游戏开发中,内存管理是至关重要的一个环节。内存泄漏不仅会导致游戏运行缓慢、卡顿,严重时甚至会引发崩溃。Unity Profiler作为一个强大的性能分析工具,能够帮助开发者深入理解应用程序的内存使用情况,从而定位并解决内存泄漏问题。同时,通过实施对象池管理策略,可以显著优化内存使用,提高游戏性能。本文将结合代码示例,详细介绍如何利用Unity Profiler定位内存泄漏,并实施对象池来优化内存使用。
391 0
|
3月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
68 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
4月前
|
Java 测试技术 Android开发
Android性能测试——发现和定位内存泄露和卡顿
本文详细介绍了Android应用性能测试中的内存泄漏与卡顿问题及其解决方案。首先,文章描述了使用MAT工具定位内存泄漏的具体步骤,并通过实例展示了如何分析Histogram图表和Dominator Tree。接着,针对卡顿问题,文章探讨了其产生原因,并提供了多种测试方法,包括GPU呈现模式分析、FPS Meter软件测试、绘制圆点计数法及Android Studio自带的GPU监控功能。最后,文章给出了排查卡顿问题的四个方向,帮助开发者优化应用性能。
243 4
Android性能测试——发现和定位内存泄露和卡顿
|
5月前
|
搜索推荐 Java API
Electron V8排查问题之分析 node-memwatch 提供的堆内存差异信息来定位内存泄漏对象如何解决
Electron V8排查问题之分析 node-memwatch 提供的堆内存差异信息来定位内存泄漏对象如何解决
143 0
|
6月前
|
编译器
8086 汇编笔记(六):更灵活的定位内存地址的方法
8086 汇编笔记(六):更灵活的定位内存地址的方法
|
7月前
|
存储 监控 算法
【JVM】如何定位、解决内存泄漏和溢出
【JVM】如何定位、解决内存泄漏和溢出
281 0
|
8月前
|
Java Shell
java中jvm使用jststak定位线程cpu占用内存高的线程
java中jvm使用jststak定位线程cpu占用内存高的线程
60 5
|
8月前
|
存储 缓存 监控
深入解析linux内存指标:快速定位系统内存问题的有效技巧与实用方法(free、top、ps、vmstat、cachestat、cachetop、sar、swap、动态内存、cgroops、oom)
深入解析linux内存指标:快速定位系统内存问题的有效技巧与实用方法(free、top、ps、vmstat、cachestat、cachetop、sar、swap、动态内存、cgroops、oom)
1419 0

热门文章

最新文章