使用方法

启动使用CONFIG_DEBUG_KMEMLEAK=y重新构建的内核,kmemleak线程就会每隔10分钟扫描一次内存。

当检测出可能存在内存泄漏时,就会输出信息。不需要进行设置等。

本节通过在样本程序中刻意加入内存泄漏,确认kmemleak检测出内存泄漏的过程。使用的内核版本为2.6.35。

然后准备用来造成内存泄漏的内核模块kmleak.c,进行编译。在所分配的内存区域写入了字符串memory leak test。


cat kmleak.c

include<linux/module.h>

include<linux/slab.h>

static int leak_func(void)

{

char*p;

char mark[]="memory leak test";

p=kmalloc(sizeof(mark),GFP_KERNEL);

if(!p){

printk("kmleak can't allocate memory\n");

return-ENOMEM;

}

printk("pointer to the allocated memory:%p\n",p);信息

memcpy(p,&mark, sizeof(mark));

if(!p)这里就是错误

kfree(p);不释放

return 0;

}

static int__init kmleak_init(void)

{

leak_func();

return 0;

}

static void__exit kmleak_exit(void)

{

return;

}

module_init(kmleak_init);

module_exit(kmleak_exit);


准备内核模块用的Makefile,编译模块。向make的-C选项指定内核2.6.35的路径。

cat Makefle

obj-m:=kmleak. o

ls

kmleak. c Makefile linux-2.6.35

make-C./linux-2. 6.35 M=pwdmodules

编译完成后,就生成了kmleak.ko。然后将这个模块安装到内核中,接着从内核中卸载。


insmod./kmleak.ko

lsmod

Module Size Used by

kmleak 914 0

……

rmmod kmleak


在释放内存的函数kfree()不调用的情况下,该内存的持有者消失。kmemleak如果执行内存扫描,就会输出表示内存泄漏的信息。kmemleak进行内存扫描的间隔默认为10分钟。

虽然最多只需等待10分钟就会输出信息,但也可以在任意时刻执行内存扫描。首先挂载debugfs。


mount-t debugfs nodev/sys/kernel/debug/


向/sys/kernel/debug/kmemleak文件写入字符串scan, kmemleak线程就会在这时进行内存扫描。


echo scan>/sys/kernel/debug/kmemleak


使用dmesg命令确认检测出内存泄漏的信息是否输出。


dmesg

……

pointer to the allocated memory:ffff88003c5b5960

这是kmleak模块输出的信息

kmemleak:1 new suspected memory leaks(see/sys/kernel/debug/kmemleak)

kmemleak输出的信息


这个信息会在检测出内存泄漏的可能性时显示。详细信息可以在/sys/kernel/debug/kmemleak中确认。


cat/sys/kernel/debug/kmemleak

……

unreferenced object 0xffff88003c5b5960(size 32):地址

comm"insmod",pid 6105,jiffies 4602131386(age 2520.563s)PID、jiffies

hex dump(first 32 bytes):

6d 65 6d 6f 72 79 20 6c 65 61 6b 20 74 65 73 74 memory leak test内存的内容

00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00……

backtrace:回溯

[<ffffffff813c33a3>]kmemleak_alloc+0x21/0x3e

[<ffffffff810c9aa8>]kmem_cache_alloc+0xc7/0xd6

[<ffffffffa040901a>]0xffffffffa040901a

[<ffffffff8100205f>]do_one_initcall+0x59/0x154

[<ffffffff8106ca16>]sys_init_module+0x9c/0x1da

[<ffffffff810089c2>]system_call_fastpath+0x16/0x1b

[<ffffffffffffffff>]0xffffffffffffffff


显示的内容从上到下依次输出的是内存的地址、分配这个内存的进程(PID)、内存的分配时间(jiffies)与分配后经过的时间、内存的内容(最大32位)、回溯。

/sys/kernel/debug/kmemleak参数

/sys/kernel/debug/kmemleak中还有除scan以外的参数,如表7-21所示。

使用方法 - 图1

使用方法 - 图2

下面是使用了dump参数的例子。


echo dump=0xffff88003c5b5960>/sys/kernel/debug/kmemleak

dmesg

……

pointer to the allocated memory:ffff88003c5b5960

kmemleak:1 new suspected memory leaks(see/sys/kernel/debug/kmemleak)

kmemleak:Object 0xffff88003c5b5960(size 32):

kmemleak:comm"insmod",pid 6105,jiffies 4602131386

kmemleak:min_count=1

kmemleak:count=0

kmemleak:flags=0x3

kmemleak:checksum=1470842492

kmemleak:backtrace:

[<ffffffff813c33a3>]kmemleak_alloc+0x21/0x3e

[<ffffffff810c9aa8>]kmem_cache_alloc+0xc7/0xd6

[<ffffffffa040901a>]0xffffffffa040901a

[<ffffffff8100205f>]do_one_initcall+0x59/0x154

[<ffffffff8106ca16>]sys_init_module+0x9c/0x1da

[<ffffffff810089c2>]system_call_fastpath+0x16/0x1b

[<ffffffffffffffff>]0xffffffffffffffff


内核启动参数

在安装了kmemleak的内核中,要禁用kmemleak功能,需要在内核启动参数中设置kmemleak=off。