嵌入式内核可加载模块编译报错:asm/linkage.h未找到
问题分析与解决
核心错误
你的Makefile混淆了内核模块编译和用户态程序编译的流程——你试图用普通gcc直接编译内核模块,这完全不符合内核模块的构建规则。内核模块必须通过内核自带的Kbuild系统编译,不能像编译普通应用那样直接调用gcc。
问题拆解
- 你定义的
helloworld目标是用$(CROSS_COMPILE)gcc -I$(INC) $^ -o $@直接编译,这是用户态程序的编译方式。但内核依赖的架构相关头文件(比如asm/linkage.h)不在kernel-source/include目录,而是在kernel-source/arch/arm64/include/asm路径下,手动添加-I参数无法覆盖内核构建系统的完整头文件路径规则。 - 你已经写对了内核模块编译的核心规则(
obj-m += helloworld.o和内核Makefile调用命令),但多余的helloworld目标导致你执行了错误的编译流程。
修正后的Makefile
export CROSS_COMPILE := aarch64-linux-gnu- export ARCH := arm64 obj-m += helloworld.o # 注意:KDIR必须指向已完成配置+编译的内核源码目录,不能是未编译的源码包 KDIR := /home/gfine/ls1043a_02142023/build_ls1043ardb/tmp/work-shared/ls1043ardb/kernel-source all: make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) -C $(KDIR) modules clean: make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) -C $(KDIR) clean rm -f *.o *.ko *.mod.* *.symvers *.order
关键注意事项
- 确保
KDIR指向的内核源码已经完成配置和编译(至少执行过make defconfig和make),内核构建需要生成的配置文件和自动生成的头文件,否则仍会出现头文件缺失问题。 - 内核模块源码(helloworld.c)需遵循内核编程规范,示例模板:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> static int __init helloworld_init(void) { printk(KERN_INFO "Hello World!\n"); return 0; } static void __exit helloworld_exit(void) { printk(KERN_INFO "Goodbye World!\n"); } module_init(helloworld_init); module_exit(helloworld_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Hello World Module"); MODULE_AUTHOR("Your Name");
为什么之前的方法无效
asm/linkage.h这类架构相关头文件,内核编译时会自动通过-Iarch/arm64/include、-Iarch/arm64/include/generated等参数引入,同时还会添加-DMODULE、-D__KERNEL__等核心编译宏,这些都是普通gcc编译无法自动处理的,必须依赖内核Kbuild系统完成。
内容的提问来源于stack exchange,提问作者user2348447
相关产品推荐
相关产品推荐

