两个内核模块之间的交互

这里的通信可以简单点理解,就是模块B如何调用A的函数,变量或者常量。为了简化,我设计一个模块A中的一个函数为printMSG,原型为int printMSG(int n);传入的参数n表示打印几遍一个固定的字符串。模块A()源码:

其中用到了EXPORT_SYMBOL宏来表明导出printMSG这个符号。还有一个EXPORT_SYMBOL_GPL宏,导出的符号具有GPL授权。内核所有的导出符号可以通过 : cat /proc/kallsyms来查看,太多了,所以最好导出到一个文件中慢慢看。在其中就可以发现printk等等我们常见的内核函数。(理解为都是通过内核符号表中的进行交互。linux所谓的LKM有了更深的认识。内核其实就是一个大的程序,当我们动态的加载进入一个模块时,他还是内核这个大程序的一部分,所以我们可以像一个工程中那样,将函数导出到内核符号表中,再将需要调用的外部的函数声明为extern关键字,就可以方便的调用了)

分别编写两个文件的Makefile文件,先insmod b.ko,再insmod a.ko出现错误:
a:no symbol version for printmsg
a:unknown symbol printmsg(err -22)
原因:
这是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的值
只要将上面的测试程序中的caller的makefile中加上“KBUILD_EXTRA_SYMBOLS”就好了�里面已经有了去掉注释�路径改下�但必须是绝对路径。重新编译caller模块即可。 
原文地址:https://www.cnblogs.com/scu-cjx/p/6878758.html