- 使用方法
- cat kmleak.c
- include<linux/module.h>
- include<linux/slab.h>
- cat Makefle
- ls
- make-C./linux-2. 6.35 M=pwdmodules
- insmod./kmleak.ko
- lsmod
- rmmod kmleak
- mount-t debugfs nodev/sys/kernel/debug/
- echo scan>/sys/kernel/debug/kmemleak
- dmesg
- cat/sys/kernel/debug/kmemleak
- echo dump=0xffff88003c5b5960>/sys/kernel/debug/kmemleak
- dmesg
使用方法
启动使用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所示。
下面是使用了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。