1、通过free 看 剩余内存
# free
total used free shared buffers
Mem: 2065866752 1268113408 797753344 0 9060352
-/+ buffers/cache: 1259053056 806813696
Swap: 524283904 0 524283904
假如通过“Free”查看内存几乎耗尽,但通过top/ps命令却看不出来用户态应用程序占用太多的内存空间, 那么内核模块可能发生了内存泄露
# top -m 5
User 4%, System 2%, IOW 0%, IRQ 0%
User 49 + Nice 0 + Sys 32 + Idle 1120 + IOW 0 + IRQ 0 + SIRQ 1 = 1202
PID USER PR NI CPU% S #THR VSS RSS PCY Name
4264 system 18 -2 2% S 95 1765108K 98260K fg system_server
5145 u0_a41 20 0 2% S 41 1692144K 65372K bg com.douyu.xl.douyutv
7063 root 20 0 0% R 1 4532K 1548K fg top
2602 root RT 0 0% D 1 0K 0K fg vdec-core
2、查看Slab 内存
SLAB是Linux内核中按照对象大小进行分配的内存分配器。
通过SLAB的信息来查看内核模块占用的内存空间:
方法1. 查看meminfo文件
# cat /proc/meminfo | grep Slab
Slab: 121588 kB
++++++++++++++++++++++++++++++++++++++++++++++++++++++
方法2. 查看slabinfo文件
# cat /proc/slabinfo
slabinfo - version: 2.1
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
cifs_small_rq 31 32 448 8 1 : tunables 54 27 8 : slabdata 4 4 0
cifs_request 5 5 16512 1 8 : tunables 8 4 0 : slabdata 5 5 0
cifs_oplock_structs 0 0 64 59 1 : tunables 120 60 8 : slabdata 0 0 0
......
size-32 29904 29904 32 112 1 : tunables 120 60 8 : slabdata 267 267 0
kmem_cache 156 156 2688 1 1 : tunables 24 12 8 : slabdata 156 156 0
一般查看slabinfo文件就足以,如果发现slabinfo中占用内存过大,那基本可以断定,内核模块出现了内存泄露了
还有个命令 slabinfo 也是可以看,其实也是去读 /proc/slabinfo 后可视化出来
3.Kmemleak工具
kmemleak的简单使用
Demo:
看看下面这个函数是哪里导致的内存泄漏呢?
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 成对出现的。
问题正好出在 pr_debug 这个函数中的参数传递, 熟悉函数调用传参的人应该会知道编译器一般对参数的处理采用堆栈的方式,是一个先进后出的过程,这样参数的执行一般是逆序的(由于编译器实现的不同,这个过程不是确定的),这样kfree会在kmalloc之前运行,导致每次运行都会泄漏一点内存。
网友评论