kmemleak 是一个类似在kernel 里面的Valgrind, 可以检测kernel 模块的memory leak情况。
至于如何使用,kernel 里面自己的文档就已经写的很清楚,可以参考: Documentation/dev-tools/kmemleak.rst
如果出现如下错误:
# echo scan > /sys/kernel/debug/kmemleak
sh: write error: Operation not permitted
这个可能是在kernel中的配置使能了CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF 或者是boot arg里面有:kmemleak=off 。
解决办法就是去掉 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF 这个配置或者在bootargs 里面加上 kmemleak=on 即可解决。
参考如下log:
# modprobe kmemleak-test
[ 560.184144] kmemleak: Kmemleak testing
[ 560.184233] kmemleak: kmalloc(32) = (____ptrval____)
[ 560.184335] kmemleak: kmalloc(32) = (____ptrval____)
[ 560.184436] kmemleak: kmalloc(1024) = (____ptrval____)
[ 560.184538] kmemleak: kmalloc(1024) = (____ptrval____)
[ 560.184640] kmemleak: kmalloc(2048) = (____ptrval____)
[ 560.184742] kmemleak: kmalloc(2048) = (____ptrval____)
[ 560.184843] kmemleak: kmalloc(4096) = (____ptrval____)
[ 560.184946] kmemleak: kmalloc(4096) = (____ptrval____)
[ 560.185164] kmemleak: vmalloc(64) = (____ptrval____)
[ 560.185368] kmemleak: vmalloc(64) = (____ptrval____)
[ 560.185573] kmemleak: vmalloc(64) = (____ptrval____)
[ 560.185778] kmemleak: vmalloc(64) = (____ptrval____)
[ 560.185984] kmemleak: vmalloc(64) = (____ptrval____)
[ 560.186086] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.186193] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.186299] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.186488] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.186595] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.186701] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.186809] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.186916] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.187023] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.187131] kmemleak: kzalloc(sizeof(*elem)) = (____ptrval____)
[ 560.187239] kmemleak: kmalloc(129) = (____ptrval____)
[ 560.187339] kmemleak: kmalloc(129) = (____ptrval____)
[ 560.187440] kmemleak: kmalloc(129) = (____ptrval____)
[ 560.187540] kmemleak: kmalloc(129) = (____ptrval____)
[ 560.187641] kmemleak: kmalloc(129) = (____ptrval____)
[ 560.187743] kmemleak: kmalloc(129) = (____ptrval____)
[ 560.187843] kmemleak: kmalloc(129) = (____ptrval____)
[ 560.187944] kmemleak: kmalloc(129) = (____ptrval____)
# echo scan > /sys/kernel/debug/kmemleak
[ 696.107594] kmemleak: 12 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
#
# cat /sys/kernel/debug/kmemleak
unreferenced object 0xffff00080089f9a0 (size 32):
comm "modprobe", pid 153, jiffies 4295032338
hex dump (first 32 bytes):
cf df df df df df df cf cf df df df df df df cf ................
c0 f9 89 00 08 00 ff ff cf df df df df df df cf ................
backtrace (crc 271abd9a):
[<(____ptrval____)>] kmemleak_alloc+0x34/0x40
[<(____ptrval____)>] kmalloc_trace+0x1d8/0x284
[<(____ptrval____)>] kmemleak_test_init+0x50/0x2a8 [kmemleak_test]
[<(____ptrval____)>] do_one_initcall+0x80/0x1c8
[<(____ptrval____)>] do_init_module+0x60/0x218
[<(____ptrval____)>] load_module+0x1bbc/0x1d88
[<(____ptrval____)>] init_module_from_file+0x88/0xcc
[<(____ptrval____)>] __arm64_sys_finit_module+0x1dc/0x2e4
[<(____ptrval____)>] invoke_syscall+0x48/0x114
[<(____ptrval____)>] el0_svc_common.constprop.0+0x40/0xe0
[<(____ptrval____)>] do_el0_svc+0x1c/0x28
[<(____ptrval____)>] el0_svc+0x34/0xd8
[<(____ptrval____)>] el0t_64_sync_handler+0x120/0x12c
[<(____ptrval____)>] el0t_64_sync+0x190/0x194
Comments !