如何导出汇编编写的内核函数?PowerPC模块调用dcache函数遇阻求助
我之前在PowerPC平台做内核模块开发时碰到过完全一样的问题,结合你描述的细节,问题出在两个核心点上:这些dcache函数没有被导出到内核符号表,同时你的模块代码里缺少函数原型声明。下面是具体的原因分析和解决步骤:
问题分析
你遇到的两个错误(隐式声明、符号未找到)是关联的:
- 符号未导出:虽然
clean_dcache_range()用_GLOBAL声明为全局符号,但这个宏仅让符号在内核内部可见,并没有把它加入到内核导出符号表中。内核模块是独立编译的,必须依赖内核主动导出的符号才能完成链接,所以这些函数不会出现在Module.symvers里,模块编译时自然找不到。 - 缺少函数原型:内核公开头文件里可能没有包含这些函数的声明(或者你没引入正确的头文件),导致GCC编译模块时无法识别函数类型,报"implicit declaration"错误。
解决步骤
1. 修改内核源码,导出需要的dcache函数
你需要修改$KERNEL_SOURCE/arch/powerpc/kernel/misc_32.S,在每个需要的函数定义后添加导出宏:
_GLOBAL(clean_dcache_range) /* 原有的汇编实现代码 */ EXPORT_SYMBOL(clean_dcache_range) # 若模块遵循GPL许可,建议用EXPORT_SYMBOL_GPL
如果还需要其他dcache函数(比如invalidate_dcache_range),同样在它们的定义后添加对应的导出宏。
完成修改后,重新编译整个内核,这样新生成的Module.symvers就会包含这些导出的符号了。
2. 在模块中添加函数声明(或包含正确头文件)
有两种方式解决隐式声明的问题:
- 方式一:手动声明函数
在你的模块.c文件顶部添加函数原型声明:
extern void clean_dcache_range(unsigned long start, unsigned long end); extern void invalidate_dcache_range(unsigned long start, unsigned long end); // 其他你需要的dcache函数
- 方式二:检查并包含对应头文件
查看PowerPC专属内核头文件arch/powerpc/include/asm/cacheflush.h,如果里面已经有这些函数的声明,直接在模块中引入:
#include <asm/cacheflush.h>
3. 重新编译你的内核模块
确保模块的Makefile正确指向了重新编译后的内核源码目录,示例Makefile如下:
obj-m += your_module.o KERNELDIR ?= /path/to/your/rebuilt/kernel/source PWD := $(shell pwd) all: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
执行编译后,之前的两个错误应该就会消失了。
补充说明
- 关于
EXPORT_SYMBOLvsEXPORT_SYMBOL_GPL:如果你的模块遵循GPL许可,建议使用EXPORT_SYMBOL_GPL,这符合内核的许可规范要求;如果模块是非GPL的,只能使用EXPORT_SYMBOL导出的符号。 - 为什么必须重新编译内核?因为导出符号的信息是在编译内核时生成到
Module.symvers中的,仅编译misc_32.S单个文件不会更新全局的符号表信息,所以需要全量编译内核。
内容的提问来源于stack exchange,提问作者m4s0ud
相关产品推荐
相关产品推荐

