项目场景:
一份源代码支持多个产品类别,多个产品类别的硬件传感器列表都是相差不大。能不能把硬件传感器的linux驱动代码作为公共代码(common),提供个多个产品类别使用呢?
问题描述
现在的问题:“公共的传感器驱动” 代码中,需要调用 “产品类别” 目录中定义的函数。这时候编译出来的内核模块运行起来就会报错:“公共的传感器驱动” 代码中无法调用“产品类别” 目录中定义的函数,即使是通过 EXPORT_SYMBOL_GPL
导出的函数也没用。
原因分析:
可以看到:其中一个 .c 源代码定义了函数 common_lpc_to_cpld_get,并且导出符号:EXPORT_SYMBOL_GPL(common_lpc_to_cpld_get); 另外一个 .c 源代码,负责调用该函数,并且在代码也声明了该函数属于外部定义的函数:extern int common_lpc_to_cpld_get(int reg);
解决方案:
在原因分析的截图中,可以看到,common_lpc_to_cpld_get 函数确实是存在符号表中的。
我们还看到,“公共的传感器驱动” 代码中编译也会产生符号表。但是这个符号表的内容为空。
因此,我们断定:因为有两个符号表,并且两个符号表没有产生联系,所以才导致 “公共的传感器驱动”代码找不到相应的导出函数符号。
我们可以使用 KBUILD_EXTRA_SYMBOLS 符号进行 makefile 编译,如在 “公共的传感器驱动”的 makefile 文件使用语句:KBUILD_EXTRA_SYMBOLS=/modules/Module.symvers ,就可以连接 “产品类别”目录中的符号表。
make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$(COMMON_DIR)/$${cpu}/ KBUILD_EXTRA_SYMBOLS=$(MOD_SRC_DIR)/$${mod}/modules/Module.symvers
可以看到编译后,原先为空的符号表中,现在已经填入了链接的modules/Module.symvers 符号表。这样内核模块运行的时候,就能正常找到符号了。