18

一次解决Linux内核内存泄漏实战全过程

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzAwMDUwNDgxOA%3D%3D&%3Bmid=2652668814&%3Bidx=1&%3Bsn=f370d176e9d3d03bb6a99f0a964362b4
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

什么是内存泄漏:

程序向系统申请内存,使用完不需要之后 , 不释放内存还给系统回收,造成申请的内存被浪费 .

发现系统中内存使用量随着时间的流逝,消耗的越来越多,例如下图所示:

MFZBvi7.png!mobile

接下来的排查思路是 :

1. 监控系统中每个用户进程消耗的 PSS ( 使用 pmap 工具 (pmap pid)).

PSS: 按比例报告的物理内存,比如进程 A 占用 20M 物理内存,进程 B 和进程 A 共享 5M 物理内存,那么进程 A PSS 就是 (20 - 5) + 5/2 = 17.5M

2. 监控 /proc/meminfo 输出 , 重点观察 Slab 使用量 slab 对应的 /proc/slabinfo 信息

3. 参考 /proc/meminfo 输出,计算系统中未被统计的内存变化,比如内核驱动代码

直接调用 alloc_page() buddy 中拿走的内存不会被单独统计

以上排查思路分别对应下图中的 1,2,3 :

2QfiEjR.png!mobile

在排查的过程中发现系统非常空闲,都没有跑任何用户业务进程。

其中在使用 slabtop 监控 slab 的使用情况时发现 size-4096 不停增长

2MR77rY.png!mobile

通过监控 /proc/slabinfo 也发现 SReclaimable 的使用量不停增长

while true; 
do
sleep 1 ;
cat /proc/slabinfo >> /tmp/slabinfo.txt ;
echo "===" >> /tmp/slabinfo.txt ;
done

由此判断很可能是内核空间在使用 size-4096 时发生了内存泄漏 .

接下来使用 trace event(tracepoint) 功能来监控 size-4096 的使用和释放过程,

主要用来跟踪 kmalloc() kfree() 函数对应的 trace event, 因为他们的 trace event 被触发之后会打印 kmalloc() kfree() 所申请和释放的内存地址 , 然后进一步只过滤申请 4096 字节的情况。

#trace-cmd record -e kmalloc
-f 'bytes_alloc==4096' -e kfree -T

(-T 打印堆栈 )

等待几分钟之后

#ctrl  ^c 中断 trace-cmd

#trace-cmd report

以上步骤相当于:

feuY3yM.png!mobile

等待几分钟之后

#cp /sys/kernel/debug/tracing/trace_pipe  /tmp/kmalloc-trace

trace-cmd report 的输出结果来看,很多 kmalloc 对应的 ptr 值都 没有 kfree 与之对应 ptr

fUbInyq.png!mobile

这就说明了 cat 进程在内核空间使用 size-4096 之后并没有释放,造成了内存泄漏。

为了进一步精确定位到是使用哪个内核函数造成的问题,此时手动触发 vmcore

#echo c > /proc/sysrq-trigger

然后使用 crash 工具分析 vmcore

#crash ./vmcore ./vmlinux.debug

读出上面 kmalloc 申请的 ptr 内存信息

ZnUjaaV.png!mobile

( 读取 0xffff880423744000 内存开始的 4096 个字节,并以字符形式显示 )

Mnm6vuB.png!mobile

发现从上面几个 ptr 内存中读出的内容都是非常相似,仔细看一下发现都是 /proc/schedstat 的输出内容。

通过阅读相关代码发现,当读出 /proc/schedstat 内容之后,确实没有释放内存

i2mIvaR.png!mobile

然后发现 kernel 上游已经有 patch 解决了这个问题:

commit: 8e0bcc722289

fix a leak in /proc/schedstats

更多精彩,尽在"Linux阅码场",扫描下方二维码关注

ZVZVjqE.jpg!mobile

MNryQvf.gif!mobile

别忘了分享、点赞或者在看哦~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK