问题:
在嵌入式target上insmod kmods失败。
root@rootfs:/lib/modules/2.6.36# insmod helloExample.ko
[5646.820000] helloExample: no symbol version for module_layout
kmod: failed to insert helloExample.ko
而且,加载kernel内可编成module的模块也有这个问题?!编进kernel则没有问题。
尝试:
网上的资料,
一说内核build目录下没有Module.symvers
确认内核编译下面肯定是有生成这个文件的。
一说kmod的Makefile中必须添加明确的KERNELDIR
all clean :
$(MAKE) -C $(KERNELDIR) M=`pwd` $@
绝对路径KERNELDIR添加后依旧不行
Kmod的版本检查机制
内核编译后的生成的Module.symvers,此文件内计算出了内核中所有被EXPORT修饰的符号。格式为:
0xea147363 printk vmlinux EXPORT_SYMBOL
如果新的kmod中使用了内核或者其他kmod的符号,那么这些符号必须在Module.symvers,否则在insmod时,就会有Unknown symbol in module的错误。
除了有符号是否存在的检测外,还有一项更严格的符号CRC的检测,kmod在编译过程中,工具modpost被scripts/Makefile.modpost调用,生成*.mod.c 及文件Module.symvers。若打开了内核选项CONFIG_MODVERSIONS,Makefile.Build就调用genksyms进一步生成符号CRC信息。
*.mod.c此文件一般组织如下:
-
#include <linux/module.h>
-
-
#include <linux/vermagic.h>
-
-
#include <linux/compiler.h>
-
-
-
-
MODULE_INFO(vermagic, VERMAGIC_STRING);
-
-
-
-
struct module __this_module
-
-
__attribute__((section(".gnu.linkonce.this_module"))) = {
-
-
.name = KBUILD_MODNAME,
-
-
.init = init_module,
-
-
#ifdef CONFIG_MODULE_UNLOAD
-
-
.exit = cleanup_module,
-
-
#endif
-
-
.arch = MODULE_ARCH_INIT,
-
-
};
-
-
-
-
static const struct modversion_info ____versions[]
-
-
__used
-
-
__attribute__((section("__versions"))) = {
-
-
{ 0xb116f561, "ppp_rxstats_upd" },
-
-
{ 0x941882cf, "ppp_txstats_upd" },
-
-
};
-
-
-
-
static const char __module_depends[]
-
-
__used
-
-
__attribute__((section(".modinfo"))) =
-
- "depends=ppp_generic";
其中modversion_info ____versions[]这个数组内,是模块引用的外部符号CRC值和名称的总表。那么在insmod kmod时,若此处的CRC值与内核中的符号CRC值不符合,也会导致模块加载失败。
*.mod.c中定义了ko文件的三个section及其内容。Mod加载时的检验信息正是存放其中。
objdump --section=.modinfo –s kmod.ko
- drivers/net/ctf/ctf.ko: file format elf32-little
- Contents of section .modinfo:
- 0000 6c696365 6e73653d 50726f70 72696574 license=Propriet
- 0010 61727900 64657065 6e64733d 00000000 ary.depends=....
- 0020 7665726d 61676963 3d322e36 2e33362e vermagic=2.6.36.
- 0030 34627263 6d61726d 20534d50 20707265 4brcmarm SMP pre
- 0040 656d7074 206d6f64 5f756e6c 6f616420 empt mod_unload
- 0050 6d6f6476 65727369 6f6e7320 41524d76 modversions ARMv
- 0060 37200000 7 ..
======================================================
这个问题到最后其实非常简单,因为内核编译时恰好有很多关于EXPOR_SYMBOL的告警,想得复杂了。要解决这个问题,就把menuconfig的CONFIG_MODVERSIONS和CONFIG_MODULE_SRCVERSION_ALL关掉即可。如此Module.symvers中就不会计算符号的CRC,而*.mod.c中也不会存放struct modversion_info ____versions[]。
经典教程 http://www.ibm.com/developerworks/cn/linux/l-cn-kernelmodules/