说明
- KO(kernel module)占用的内存分为两部分:
- 静态占用 :ko insmod时系统固定分配的内存。
- 动态申请 :代码中动态申请的内存,由于申请方式不同,统计的方式也可能不同,例如:使用vmalloc和kmalloc申请内存,统计方式就不同;代码是否执行以及执行次数不同,统计结果也不同。
静态占用
- KO静态占用内存是通过vmalloc分配的, 主要分为两部分
- core_layout
- init_layout
-
可通过linux内核代码确认。
// 文件:linux_5.10/kernel/module.c
static struct module *layout_and_allocate(struct load_info *info, int flags)
{
...
ndx = find_sec(info, ".data..ro_after_init");
if (ndx)
info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;
...
ndx = find_sec(info, "__jump_table");
if (ndx)
info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;/* Determine total sizes, and put offsets in sh_entsize. For now this is done generically; there doesn't appear to be any special cases for the architectures. */ layout_sections(info->mod, info); layout_symtab(info->mod, info); /* Allocate and move to the final place */ err = move_module(info->mod, info); if (err) return ERR_PTR(err); /* Module has been copied to its final place now: return it. */ mod = (void *)info->sechdrs[info->index.mod].sh_addr; kmemleak_load_module(mod, info); return mod;
}
static int move_module(struct module *mod, struct load_info info)
{
...
/ Do the allocs. */
ptr = module_alloc(mod->core_layout.size);
...
if (mod->init_layout.size) {
ptr = module_alloc(mod->init_layout.size);
...
}
...
}void * __weak module_alloc(unsigned long size)
{
// 使用vmalloc申请内存
return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
GFP_KERNEL, PAGE_KERNEL_EXEC, VM_FLUSH_RESET_PERMS,
NUMA_NO_NODE, __builtin_return_address(0));
}
占用统计
- lsmod 或 /proc/modules
-
lsmod打印的KO列表中有个size属性,表示KO内存占用。
-
lsmod 的数据来自/proc/modules。
~# lsmod
Module Size Used by Tainted: GF
xxxx_ive 234750 0
xxx_ipcm 84490 0
xxxx_tpu 26507 0
xxxx_clock_cooling 4685 0
xxxx_sys 21052 1 xxxx_ive
~# cat /proc/modules
xxxx_ive 234750 0 - Live 0xffffffdf808a5000 (FO)
xxx_ipcm 84490 0 - Live 0xffffffdf80881000 (FO)
xxxx_tpu 26507 0 - Live 0xffffffdf80873000 (FO)
xxxxx_clock_cooling 4685 0 - Live 0xffffffdf8086e000 (FO)
xxxxx_sys 21052 1 xxxx_ive, Live 0xffffffdf80863000 (FO) -
/proc/modules显示的size包括KO的init_size和core_size,少于实际静态占用,可通过以下节点查看分别大小。
~# cat /sys/module/xxxx_sys/initsize
~# cat /sys/module/xxxx_sys/coresize
-
cat /proc/meminfo 查看vmallocUsed 项,cat /proc/vmallocinfo 中查看单个KO的内存占用。
~# cat /proc/meminfo
....
VmallocTotal: 67108863 kB
VmallocUsed: 2564 kB
VmallocChunk: 0 kB
....
~# cat /proc/vmallocinfo
....
0x(ptrval)-0x(ptrval) 28672 load_module+0x6fa/0x1c5a pages=6 vmalloc
0x(ptrval)-0x(ptrval) 12288 load_module+0x6fa/0x1c5a pages=2 vmalloc
0x(ptrval)-0x(ptrval) 32768 load_module+0x6fa/0x1c5a pages=7 vmalloc
0x(ptrval)-0x(ptrval) 90112 load_module+0x6fa/0x1c5a pages=21 vmalloc
0x(ptrval)-0x(ptrval) 241664 load_module+0x6fa/0x1c5a pages=58 vmalloc
....
- 有些平台上VmallocUsed 显示为0 KB。
区别
* xxxx_ive
lsmod size: 234750
vmallocinfo size: 241664
- 看/proc/vmallocinfo 中的数据和lsmod 数据差别在两点:
- 内存页(4096)对齐
- 多一内存页(栅栏页)
整体占用统计方法
- insmod/rmmod ko后cat /proc/meminfo 看available变化(但是不是很准确)。