如何确定Linux内核模块是否泄漏内存

kak*_*ada 9 memory-management kernel-module linux-kernel

为了测试内核泄漏内存时的行为,我正在编写一个内核模块,它不断分配内存,例如代码

int bytesLeaked = 128000;
char *var = kmalloc(bytesLeaked, GFP_KERNEL); 
if (var != NULL)
printk("leaked %d bytes at address %x\n", bytesLeaked, (unsigned int)var);
Run Code Online (Sandbox Code Playgroud)

此代码位于init_module中.我有以下问题

  1. 如何确定代码是否泄漏了内存?lsmod并没有透露太多.
  2. 互联网上的教程仅显示init_module和exit_module中的代码.如果我希望在插入模块之后但在退出之前的一段时间内进行内存分配,该怎么办?
  3. 我是否有可能只在用户给出指令时才编写泄漏内存的代码,例如用户空间程序是否可以进行系统调用,这会导致模块泄漏内存?

Eug*_*ene 18

如果你需要检查一个内核模块是否泄漏了内存并且你的机器有x86架构,你可以使用KEDR系统,它包括一个内存泄漏检测器.

KEDR不要求您重建内核.在线文档(例如,参见"入门")描述了如何安装和使用KEDR.简而言之,程序如下.

安装(来源):untar源档案 - cmake <...> - make - make install

在加载模块之前启动KEDR:

$ kedr start <name_of_the_module_to_analyze> -f leak_check.conf
Run Code Online (Sandbox Code Playgroud)

然后您可以像往常一样加载模块并使用它.卸载后,KEDR会在debugfs中给你一个报告(通常安装debugfs /sys/kernel/debug),例如:

$ cat /sys/kernel/debug/kedr_leak_check/info
Target module: "...", 
Memory allocations: 3
Possible leaks: 2
Unallocated frees: 0
Run Code Online (Sandbox Code Playgroud)

文件possible_leaks/sys/kernel/debug/kedr_leak_check/提供有关每个泄漏的内存块信息(地址,大小,调用栈).

最后,你可以停止KEDR(注意/sys/kernel/debug/kedr_leak_check/会消失):

kedr stop
Run Code Online (Sandbox Code Playgroud)

如果您使用的系统的结构不是x86,那么Kmemleak也可能会有所帮助,尽管使用它有点困难.您可能需要使用CONFIG_DEBUG_KMEMLEAK参数设置为'y'来重建内核.不过,Kmemleak也是一个非常有用的工具.有关详细信息,请参阅内核源代码中的Documentation/kmemleak.txt.

  • KEDR支持2.6.31或更新的内核版本.我的是2.6.28.看起来像KEDR不能使用.我将尝试为我的内核找到类似的工具 (2认同)

aro*_*oth 0

  1. 当代码分配一块内存(例如 with kmalloc()),然后丢失对该内存块的所有引用而没有先释放它时,代码就会泄漏内存。您的代码尚未执行此操作,因为您仍然var在范围内并指向您的内存块。如果你添加var = NULL;下一行,那么你就有了真正的内存泄漏。

  2. 并且绝对有可能拥有它,以便用户空间中的事件触发内核模块开始分配内存。我不确定您是否可以直接通过系统调用来完成此任务,但如果不能,那么还有许多其他方法可以完成该任务。您只需要选择一个并实施它。touch即使是像每次想要触发内存分配时都有一个预先确定的文件这样简单的事情也应该可以工作。虽然我不明白为什么你不能让你的init_module代码生成一个只随着时间的推移定期分配内存的线程,如果这是你想要的行为。

  • re 1:内存泄漏的定义属性是分配的内存永远不会被释放,不一定是没有对其的引用。另外,“var”可能会在某个时间点超出范围,此时您的引用计数无论如何都会变为 0。(让我们忽略“引用”在 C 语言中没有明确定义的事实。) (4认同)