[英]Porting module to newer Linux kernel: Cannot allocate memory
我有一个非常大的驱动程序模块,我正在尝试编译最近的Linux内核(3.4.4)。 我可以使用2.6.27.25内核成功编译和insmod
相同的模块。 GCC版本也不同,4.7.0对4.3.0。 请注意,此模块非常复杂,我不能简单地浏览所有代码和所有makefile。
当“插入”模块时,我得到一个Cannot allocate memory
使用以下跟踪Cannot allocate memory
:
vmap allocation for size 30248960 failed: use vmalloc=<size> to increase size.
vmalloc: allocation failure: 30243566 bytes
insmod: page allocation failure: order:0, mode:0xd2
Pid: 5840, comm: insmod Tainted: G O 3.4.4-5.fc17.i686 #1
Call Trace:
[<c092702a>] ? printk+0x2d/0x2f
[<c04eff8d>] warn_alloc_failed+0xad/0xf0
[<c05178d9>] __vmalloc_node_range+0x169/0x1d0
[<c0517994>] __vmalloc_node+0x54/0x60
[<c0490825>] ? sys_init_module+0x65/0x1d80
[<c0517a60>] vmalloc+0x30/0x40
[<c0490825>] ? sys_init_module+0x65/0x1d80
[<c0490825>] sys_init_module+0x65/0x1d80
[<c050cda6>] ? handle_mm_fault+0xf6/0x1d0
[<c0932b30>] ? spurious_fault+0xae/0xae
[<c0932ce7>] ? do_page_fault+0x1b7/0x450
[<c093665f>] sysenter_do_call+0x12/0x28
-- clip --
显而易见的答案似乎是模块分配了太多内存,但是:
因此,我怀疑新内核的问题与有限的内存没有直接关系。
新内核抱怨30,000 KB的vmalloc()
,但是对于旧内核,lsmod给我的大小为4,800 KB。 这些数字应该直接相关吗? 是否有可能在构建过程中出现问题并且要求RAM太多? 当我编译两个.ko
的部分大小时,我没有看到很大的差异。
所以我试图了解问题的来源。 当我检查转储堆栈时,我无法找到匹配的代码段。 似乎错误的vmalloc()
是由sys_init_module()
完成的,它是来自kernel/module.c
init_module()
。 但代码不匹配。 当我从.ko
检查目标代码时, init_module()
代码也不匹配。
我或多或少被阻止,因为我不太了解内核,并且所有构建系统和模块加载都很难理解。 在加载模块之前发生错误,因为我怀疑某些功能缺失,而insmod
不会报告这些错误。
我相信分配是在layout_and_allocate
完成的,由load_module
。 两者都是静态函数,因此它们可能是内联的,因此不在堆栈中。
所以它不是由您的代码完成的分配,而是由Linux完成的分配以加载您的代码。
如果你的旧内核是4.8MB而新的内核是30MB,它可以解释它失败的原因。
所以问题是为什么它如此之大。
大小可能是由于代码量(不太可能增长太多)或静态分配的数据。
一个可能的解释是你有一个大的静态分配数组,其大小在Linux中定义。 如果尺寸显着增加,您的阵列将会增长。
猜测 - 一个大小为NR_CPUS
的数组。
您应该能够使用诸如nm
或objdump
类的命令来查找这样的数组。 但是我不知道究竟是怎么做到的。
问题实际上是由于模块中的调试部分。 旧内核能够忽略这些部分,但是新部分正在计算它们的总大小以进行分配。 但是,在加载时从module.c启用pr_debug()
跟踪时,这些部分不会与其他部分一起转储。
如何摆脱它们并解决问题:
objcopy -R .debug_aranges \
-R .debug_info \
-R .debug_abbrev \
-R .debug_line \
-R .debug_frame \
-R .debug_str \
-R .debug_loc \
-R .debug_ranges \
orignal.ko new.ko
此项目的特定构建文件也可能为旧内核版本添加“定制”的调试信息,但是当尝试使用虚拟模块时,我发现附加的调试部分完全相同,所以我宁愿怀疑一些关于内核或Fedora中的模块管理的策略更改。
欢迎任何有关这些变化的信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.