kmemleak
kmemleak 是 Linux 内核中用于检测 内核内存泄漏(memory leak) 的工具,工作方式类似于用户空间中的垃圾回收器标记-扫描算法。它能帮助开发者查找在内核中分配但未释放、也没有任何引用指针指向的内存区域。
工作原理
- 分配跟踪:对内核中某些常见的内存分配函数(如 kmalloc, vmalloc, kmem_cache_alloc 等)打钩,记录每一次分配的地址、大小、调用栈信息。
- 引用扫描:周期性扫描内核中已知的根(如全局变量、任务栈、slab缓存等),查找指向上述分配内存的指针。
- 未被引用的对象:如果某块内存不能从任何已知根中访问到,认为它“可能”泄漏,并标记为 leak。
启用方式
- 编译内核时打开 kmemleak 选项:
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=n
- 启动参数添加:
kmemleak=on
- 确认内核是否编译支持 kmemleak
zcat /proc/config.gz | grep KMEMLEAK
你应该看到这些配置:
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=n
- 使用方法
mount -t debugfs debugfs /sys/kernel/debug
echo scan > /sys/kernel/debug/kmemleak
cat /sys/kernel/debug/kmemleak
- 检测到泄漏时,你会看到类似输出:
unreferenced object 0xffff908c436a4380 (size 128):
comm "insmod", pid 104, jiffies 4295071470 (age 28.527s)
hex dump (first 32 bytes):
70 65 72 2f 30 00 00 00 00 00 00 00 69 4e 72 2a per/0.......iNr*
00 00 00 00 00 00 00 00 10 be b5 be ff ff ff ff ................
backtrace:
[<(____ptrval____)>] 0xffffffffc017b022
[<(____ptrval____)>] do_one_initcall+0x3f/0x1c0
[<(____ptrval____)>] do_init_module+0x46/0x220
[<(____ptrval____)>] __do_sys_init_module+0x158/0x190
[<(____ptrval____)>] do_syscall_64+0x35/0x80
[<(____ptrval____)>] entry_SYSCALL_64_after_hwframe+0x6c/0xd6
提供一份人为引发memleak的demo
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
static void *leak_ptr;
static int __init leak_init(void)
{
pr_info("Leak demo: loading module\n");
leak_ptr = kmalloc(128, GFP_KERNEL); // 分配 128 字节,不释放
if (!leak_ptr)
return -ENOMEM;
pr_info("Allocated memory at %px (not freeing it)\n", leak_ptr);
return 0;
}
static void __exit leak_exit(void)
{
pr_info("Leak demo: unloading module\n");
// kfree(leak_ptr); // 故意不释放 leak_ptr -> 制造内存泄漏
pr_info("Leaked memory at %px\n", leak_ptr);
}
module_init(leak_init);
module_exit(leak_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Joshua Zhong");
MODULE_DESCRIPTION("Deliberate memory leak for kmemleak test");
编译后insmod这个ko,再rmmod之。
注意事项
- kmemleak 不能检测引用环(如 A 引用 B,B 引用 A)
- 它是标记-清除算法,以不可达对象为泄漏依据
- 一些内核分配器(如 vmalloc)可能不完全支持
2145

被折叠的 条评论
为什么被折叠?



