最近在加载驱动时遇到这个问题,在网上搜了下,故转载下:http://blog.csdn.net/hshl1214/article/details/8769112
前几天一个同事问我:如果一个模块要调用另一个模块的函数,要不要做什么特别的处理?我当时只是知道需要将被调用的函数EXPORT_SYMBOL();。但是由于具体的模块实验自己还没有做过,我就立马做了一个给他看,自己也验证一下。这实验一做,问题就来了:虽然在编译通过了(有警告:
- WARNING: "exported_function_2" [/home/tekkaman/development/research/Linux_module/caller/caller.ko]undefined!
),但是当把导出函数的模块挂载后,再挂载调用模块的时候出了错误无法挂载:
- # insmod exporter_1.ko
- Hello, Tekkaman Ninja !
- exported_function_1 is online!
- # insmod exporter_2.ko
- Hello, Tekkaman Ninja !
- exported_function_2 is online!
- # insmod caller.ko
- caller: no symbol version for exported_function_2
- caller: Unknown symbol exported_function_2 (err -22)
- caller: no symbol version for exported_function_1
- caller: Unknown symbol exported_function_1 (err -22)
- insmod: error inserting 'caller.ko': -1 Invalid parameters
这里先将我的测试用例分享如下,大家可以先看下代码:
(请自行修改内核源码目录和交叉编译器的定义)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在出了问题之后,我到网上google了解决方法:
其中15楼daidaiangel
的解决办法是正解,转载如下:
- 这是linux kernel 2.6.26 之后版本的bug (详细描述, 请看http://bugzilla.kernel.org/show_bug.cgi%3Fid%3D12446)
- 并且这个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的值
同时还有一篇网文作为参考,解决方法相同:
Linux内核模块加载报错”no symbol version for struct_module”解决办法
用这个方法的确可以解决问题,只要将上面的测试程序中的caller的makefile中加上“KBUILD_EXTRA_SYMBOLS”就好了(里面已经有了,去掉注释,路径改下,但必须是绝对路径哦!)。重新编译caller模块即可。
实验过程:
- root@dm816x-evm:/# insmod exporter_1.ko
- Hello, Tekkaman Ninja !
- exported_function_1 is online!
- root@dm816x-evm:/# insmod exporter_2.ko
- Hello, Tekkaman Ninja !
- exported_function_2 is online!
- root@dm816x-evm:/# insmod caller.ko
- Hello, Tekkaman Ninja !
- Now call exporters's function!
- I'm exported_function_1 !(in /home/tekkaman/development/research/Linux_module/exporter_1/exporter_1.c)
- I'm exported_function_2 !(in /home/tekkaman/development/research/Linux_module/exporter_2/exporter_2.c)