接上文:
Linux内存查看通用方法(一): user空间_红桃Jk的博客-CSDN博客_linux内存查看在嵌入式linux上,统计内存情况的一般方法https://blog.csdn.net/qq_34597963/article/details/126023451?spm=1001.2014.3001.5501
目录
一 linux整体内存分配
二 排除user空间内存泄露问题
三 确认kernel内存泄露问题
四 定位kernel泄露问题点
一 linux整体内存分配
1在user空间以外 ,还有linux的内存分配还会出现在kernel中
二 排除user空间内存泄露问题
1首先对内存使用情况进行确认,系统整体内存不断下降。 (linux : free 命令)
2然后对各模块内存进行确认
任意两次 内存比较,发现各模块内存存在变化,但没有内存泄漏现象,是正常的内存使用。
并对各模块使用的内存值(VmRSS)进行求和,发现和Used总量有较大差值。
如果 user空间发生泄露 调查方法参照
Linux内存查看通用方法(一): user空间_红桃Jk的博客-CSDN博客_linux内存查看在嵌入式linux上,统计内存情况的一般方法https://blog.csdn.net/qq_34597963/article/details/126023451?spm=1001.2014.3001.5501
当user空间的内存未看出明显泄露时,但linux整体的内存又在明显下降时
很大的可能是在kernel中出现了内存泄露
对于linux kernel 内存管理,也有一个malloc函数---->kmalloc。
但linux kernel的内存申请,有一个slab系统(伙伴系统)进行总体分配。
三 确认kernel内存泄露问题
1 slab系统也是linux 内存分配的一部分, 所以通过 cat /proc/meminfo 也可以查看到相关内容
多次检测slab,发现slab确实在不断上涨,且和内存泄漏速度成正比例关系,因此确认和slab相关
四 定位kernel泄露问题点
1 百度 linux slab 系统相关,linux也提供了相关方法
可以使用 cat /proc/slabinfo 查看总体数值 (各列含义可以自行百度)
然后对长时间观测相关变化,短时间内大量频繁变化的对象为 kmalloc-256
2 对于 slab内各对象的详细使用情况,可以在 /sys/kernel/slab中进行查看
进入 kmalloc-256
有三个关键项 ①alloc_slab ②free_slab ③trace 通过这三项可以具体查看内存使用及释放情况
3 查询此三项内容,首先应该打开linux kernel相关功能,需要重新配置 menuconfig ,否则无法cat出相关内容
方法大致如下:
通过 bitbake linux-telechips -f -c menuconfig 改变menuconfig
搜索 slub 及kmem,将相关内容状态修正为Y
4 修改完了后 在编译烧写后重新对机器进行测试。
然后 cat /sys/kernel/slab/kmalloc-256/alloc_calls 可以查看 相关申请此区域的调用履历
通过上图 可以看到 devm_pinctrl_get 调用次数最多 大概率是此项导致内存泄漏,pid =902 之后会用到
然后我们也查看一下 free_slab 的调用履历,发现没有释放此处相关的内容
首先打开 trace log开关
然后使用 dmesg 查看kernellog
就会看到输出大量的的 trace log ,
此时搜索关键词 PID 902, 可以确认他是进程 EdaTunerApplica 间接申请的内存
我们反过来查看 Tuner的进程 主进程PID 为 837
其下的全部线程ID 如下 也可以看到 子线程902,并能看到它在持续运行,连续运行时机达到42s 确实消耗了大量的内存
通过结合具体的 call trace,我们可以确认内存使用是具体的函数调用履历(driver下)
在 kernel代码中 grep 查找相关函数内容
其中 spi_tcc这个文件比较嫌疑比较大,
查看相关变更内容
5 原因确认
对于驱动函数 devm_pinctrl_get 必须配对使用 devm_pinctrl_put. 但是从代码中我们仅能看到get,没有put进行释放
tuner每次发送数据时都会调用此函数,只要tuner有声音出力,就会发生内存泄漏问题。
最后kill 掉tuner后或将增加释放相关函数,再进行实验,内存不再泄露,问题不在发生
确认原因和分析一致
参考网址
深度探究Linux内存中的/proc/meminfo参数 - 知乎 (zhihu.com)
一个驱动导致的内存泄漏问题的分析过程(meminfo->pmap->slabtop->alloc_calls) (bbsmax.com)
(153条消息) 【内存管理】【slab】/sys/kernel/slab/<slab name>/trace解析_Evan_ZGYF丶的博客-CSDN博客
slab申请释放和追踪 - 知乎 (zhihu.com)
一个驱动导致的内存泄漏问题的分析过程(meminfo->pmap->slabtop->alloc_calls) - ArnoldLu - 博客园 (cnblogs.com)
linux通过meminfo 与 slab 定位内存泄漏 - 简书 (jianshu.com)
linux kernel内核slab内存泄露debug经验 - 编程之家 (jb51.cc)
(153条消息) 内存泄露调试分析(一)_Robin.Yin的博客-CSDN博客_sunreclaim
(153条消息) Kmemleak检测工具介绍_Fybon的博客-CSDN博客
(153条消息) 内存管理四 内存泄漏检测kmemleak_frank_zyp的博客-CSDN博客
(153条消息) meminfo与vmallocinfo实例_hbcbgcx的博客-CSDN博客_/proc/vmallocinfo
(153条消息) Linux:/proc/meminfo参数详细解释_coldice0521的博客-CSDN博客_/proc/meminfo
linux内存管理中的SLAB分配器详解 - 今日头条 - 电子发烧友网 (elecfans.com)
(153条消息) top、ps命令查看进程中的线程方法_奇妙之二进制的博客-CSDN博客_top查看进程的线程
(153条消息) top和ps查看线程_lanhuazui10的博客-CSDN博客_ps 查看线程
linux 怎么查看一个进程的所有线程_百度知道 (baidu.com)
参考脚本
#!/bin/bash
a=1
echo "8 > /proc/sys/kernel/printk"
while [ $a -eq 1 ];do
echo "########################"
echo `date "+%Y-%m-%d %H:%M:%S"`
echo "free"
free -h
for pid in `ls -1 /proc/ | egrep "[[:digit:]]"`;
do if [ -f "/proc/$pid/status" ];
then proc_name=`grep '^Name' /proc/$pid/status | awk '{print $2}'`;
mem_VmPeak=`grep '^VmPeak' /proc/$pid/status | awk '{print $2}'`;
mem_VmRSS=`grep '^VmRSS' /proc/$pid/status | awk '{print $2}'`;
mem_VmSize=`grep '^VmSize' /proc/$pid/status | awk '{print $2}'`;
mem_VmData=`grep '^VmData' /proc/$pid/status | awk '{print $2}'`;
if [[ $mem_VmPeak != "" ]]; then echo "]$proc_name] VmPeak : ]$mem_VmPeak] kB VmRSS : ]$mem_VmRSS] kB VmSize : ]$mem_VmSize] kB VmData : ]$mem_VmData] kB";
fi
fi
done
echo "meminfo"
cat /proc/meminfo
echo "slabinfo"
cat /proc/slabinfo
echo "########################"
sleep 30s
done