最近在kernel driver中写一个功能,遇到module之间调用的问题,以此记录一下。
在kernel中两个不同的模块之间是不能通过简单的#include “XX.h”来相互调用函数的。如果这样在调用的地方不会出现语法错误,但是在最后生成模块文件XXX.ko时就会出现error:“xxxx” 【xxx.ko】undefined! 在生成 .ko文件(kernel object)这个时候就报资源没有定义的错误了。
出现这样的情况是因为kernel的模块都是相互独立的,如果要共享就必须做一些处理了。
以/driver中的gpio和ir这两个module为例,如下:
ir.c中调用gpio中对gpio口操作的函数:
void MDrv_GPIO_Set_High(U8 u8IndexGPIO);
一.被调用模块gpio
1.gpio.c中被调用函数必须添加EXPORT_SYMBOL声明,如下:
void MDrv_GPIO_Set_High(U8 u8IndexGPIO)
{
MHal_GPIO_Set_High(u8IndexGPIO);
}
EXPORT_SYMBOL(MDrv_GPIO_Set_High);
用EXPORT_SYMBOL声明一下函数是为了奖此函数导出,可供外部使用!
2.gpio模块中的Kconfig以及Makefile设置
Kconfig中必须定义Kernel中相对应的模块名:config MDRV_GPIO
Makefile中编译目标:
obj-$(CONFIG_MDRV_GPIO) += gpio.o
3.被调用模块上层的Makefile配置
gpio.c的上一目录driver中的Makefile中:
obj-$(CONFIG_MDRV_GPIO) += gpio/
其中gpio也就是gpio.c所在的目录。
这样MDrv_GPIO_Set_High才能被正确的导出到kernel的根目录下的Module.symvers文件,这个文件里面就是kernel里所有的EXPORT_SYMBOL和EXPORT_SYMBOL_GPL导出来的符号以及函数,EXPORT_SYMBOL_GPL和EXPORT_SYMBOL的区别就是:如果module的协议不是GPL的, 那么EXPORT_SYMBOL_GPL导出的那些符号以及函数,就用不了!
这个Module.symvers每次编译kernel的时候重新生成!
如果碰到上面的编译错误,第一步就是到这个Module.symvers中查看是否有你要调用的函数或者变量!
在ir.c中需要调用MDrv_GPIO_Set_High(U8 u8IndexGPIO):
extern void MDrv_GPIO_Set_High(U8 u8IndexGPIO);
这样ir.c中的函数就可以调用 MDrv_GPIO_Set_High(U8 u8IndexGPIO)这个函数啦!
撰写不易,转载请注明出处http://blog.csdn.net/jscese/article/details/16991679