加载驱动模块时-1 Unknown symbol in module
(2011-07-11 12:42:00)
标签:
杂谈 |
最简单的示例程序,写两个模块,分别为A和B,在A中导出了一些函数,而在B中使用A导出的函数。模块都使用GPL。
问题是在2.6.22和2.6.24下运行加载都很正常,当在2.6.26内核下加载时却出现了了Unknow symbol in module的错误。详见下面的具体描述。
两个模块的源码如下:
Makefile for Module A
Makefile for Module B
编译完成后开始加载模块:
在 /proc/kallsyms 里可以找到module A导出的symbol。
内核2.6.26版本以前都很正常,只有2.6.26版出现这个错误。
原因:
这是linux kernel 2.6.26 之后版本的bug (详细描述, 请看http://bugzilla.kernel.org/show_bug.cgi?id=12446)
并且这个bug不会被fix
解决办法是把mod_a的Module.symvers放到mod_b的当前路径,从而编译mod_b,符号信息会自动连接进去.
或者在mod_b的makefile中使用KBUILD_EXTRA_SYMBOLS指定mod_a的Module.symvers, 如:
KBUILD_EXTRA_SYMBOLS=/mod_a/Module.symvers
编译mod_b时,搜索Module.symvers的路径是:
1, kernel source path, e.g. /usr/src/kernels/linux-2.6.28.10
2, makefile中M=所指定的路径, 它等效于变量KBUILD_EXTMOD的值
3, 变量KBUILD_EXTRA_SYMBOLS的值
问题是在2.6.22和2.6.24下运行加载都很正常,当在2.6.26内核下加载时却出现了了Unknow symbol in module的错误。详见下面的具体描述。
两个模块的源码如下:
- C/C++ code
-
// Module A (mod_a.c)#include<linux/init.h>#include<linux/module.h>#include<linux/kernel.h> static int func1(void) { printk("In Func: %s...\n",__func__); return 0; } // Export symbol func1EXPORT_SYMBOL(func1); static int __init hello_init(void) { printk("Module 1,Init!\n"); return 0; } static void __exit hello_exit(void) { printk("Module 1,Exit!\n"); } module_init(hello_init); module_exit(hello_exit);
- C/C++ code
-
// Module B (mod_b.c)#include<linux/init.h>#include<linux/kernel.h>#include<linux/module.h> static int func2(void) { extern int func1(void); func1(); printk("In Func: %s...\n",__func__); return 0; } static int __init hello_init(void) { printk("Module 2,Init!\n"); func2(); return 0; } static void __exit hello_exit(void) { printk("Module 2,Exit!\n"); } module_init(hello_init); module_exit(hello_exit);
Makefile for Module A
- BatchFile code
-
obj-m += mod1.o mod1-y := mod_a.o KVERSION = $(shell uname -r) all: make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules clean: make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean rm -f *.o *.ko *.cmd
Makefile for Module B
- BatchFile code
-
obj-m += mod2.o mod2-y := mod_b.o KVERSION = $(shell uname -r) all: make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules clean: make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean rm -f *.o *.ko *.cmd
编译完成后开始加载模块:
- BatchFile code
-
#insmod ./mod1.ko #insmod ./mod2.ko FATAL: Error inserting mod2 (/home/user/test/mod2.ko): Unknown symbol in module, or unknown parameter (see dmesg)#dmesg [ 7029.008527] mod2: no symbol version for func1 [ 7029.008534] mod2: Unknown symbol func1
在 /proc/kallsyms 里可以找到module A导出的symbol。
内核2.6.26版本以前都很正常,只有2.6.26版出现这个错误。
原因:
这是linux kernel 2.6.26 之后版本的bug (详细描述, 请看http://bugzilla.kernel.org/show_bug.cgi?id=12446)
并且这个bug不会被fix
解决办法是把mod_a的Module.symvers放到mod_b的当前路径,从而编译mod_b,符号信息会自动连接进去.
或者在mod_b的makefile中使用KBUILD_EXTRA_SYMBOLS指定mod_a的Module.symvers, 如:
KBUILD_EXTRA_SYMBOLS=/mod_a/Module.symvers
编译mod_b时,搜索Module.symvers的路径是:
1, kernel source path, e.g. /usr/src/kernels/linux-2.6.28.10
2, makefile中M=所指定的路径, 它等效于变量KBUILD_EXTMOD的值
3, 变量KBUILD_EXTRA_SYMBOLS的值