1 背景介绍
内存泄漏问题是内存在申请后没有被及时释放导致,这种情况可能发生在用户空间,也可能在内核空间。
- 应用层通过
malloc/free
函数,通过 libc 库向 buddy 系统申请/释放内存 - 内核层通过
kmalloc/kfree
函数,通过 slab 模块向 buddy 系统申请/释放内存 - 内核层通过
vmalloc/vfree
函数直接向 buddy 系统申请内存,注意这一部分的内存不会被系统统计
2 初步分析
计算公式:MemTotal = MemFree +【Slab+ VmallocUsed + PageTables + KernelStack + HardwareCorrupted + Bounce + X】+【Cached + AnonPages + Buffers + (HugePages_Total * Hugepagesize)】
# 查看进程使用的物理内存
while true; do ps -e -o pid,comm,%mem | sort -n -r -k 3 | head -n 10 ;echo "----------"; sleep 1; done
# 计算使用的slab的内存并排序
while true; do cat /proc/slabinfo | awk '{name=$1; size=$2*$4/4096; printf "%s %lu\n", name, size;}' | sort -n -r -k 2 | head -n 20; echo "--------------"; sleep 1;done;
# 计算未统计的内存
while true;do cat /proc/meminfo | awk '{if($1=="Active:" || $1=="Inactive:" || $1=="Unevictable:" || $1=="Slab:" || $1=="KernelStack:" || $1=="PageTables:") u+=$2; if($1=="MemTotal:") used+=$2; if ($1=="MemFree:") used-=$2;}END{print used-u}'; sleep 1;done
3 排查思路
首先定位是哪一种内存泄漏,然后根据 trace 手段直接对函数进行分析,找出导致内存泄漏的接口调用。