前言
前面我讲了复习了几篇内核调试的文章,接下来我讲下内核下处理内存泄漏的一些工具使用。我们知道Linux内核中,分配小块内存块是用slab/slub分配器的kmalloc()/kfree()这对内存分配释放的函数,同时slab/slub分配器提供一个用于内存检测的工具slabinfo,方便在产品开发阶段进行内存检查。
本篇环境
硬件平台:飞凌OK3588开发板
内核源码:5.10.66
编译环境:Ubuntu 20.04 LTS
编译工具链:aarch64-linux-gnu-
内存访问出错的场景
我列举下常见内存访问中比较容易出错的场景如下:
-
越界访问 -
释放已经释放过的内存(重复释放同一块内存) -
访问已经释放的内存
接下来我会用slabinfo来验证上述三个内存访问出错的例子
前期准备
配置和编译内核
首先需要重新配置内核选项,打开CONFIG_SLUB和CONFIG_SLUB_DEBUG_ON这两个选项
file: arch/arm64/config/OK3588-Linux_defconfig
CONFIG_SLUB=y
CONFIG_SLUB_DEBUG_ON=y
CONFIG_SLUB_STATS=y
编译slabinfo工具
此外还需要再Linux内核的tools/vm目录下交叉编译slabinfo工具或者可以把slabinfo.c文件推到板子里进行编译
$ aarch64-linux-gnu-gcc slabinfo.c -o slabinfo
测试代码示例
我会举出上面三个内存访问出错示例进行讲解
越界访问
下面的示例用来模拟一次越界访问的场景,原来分配了32字节,但是memset()要越界访问200字节
file: slub_test.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
static char *buf;
static void create_slub_error(void)
{
buf = kmalloc(32,GFP_KERNEL);
if (buf)
memset(buf, 0x55, 200); //故意访问越界
}
static int __init my_test_init(void)
{
printk("my module init\n");
create_slub_error();
return 0;
}
static void __exit my_test_exit(void)
{
printk("my module exit");
kfree(buf);
}
MODULE_LICENSE("GPL");
module_init(my_test_init);
module_exit(my_test_exit);
MODULE_AUTHOR("pan");
MODULE_DESCRIPTION("A simple example of Memory acce