Fedora 20下简单设备驱动编译:头文件路径配置问题求助
我按照O'Reilly《Linux设备驱动》手册中的“Hello World”设备驱动示例尝试编译加载,但遇到一个问题:必须在include语句中显式指定头文件的完整路径(例如#include </usr/src/kernels/3.19.8-100.fc20.i686+PAE/include/linux/init.h>)才能成功编译,仅使用#include <linux/init.h>会出现头文件找不到的错误。
我当前的Makefile
obj-m := hello.o KDIR =/usr/src/kernels/3.19.8-100.fc20.i686+PAE/include all: make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
若保留显式include语句编译,生成的hello.mod.c文件如下,且可通过insmod正常加载:
#include <linux/module.h> #include <linux/vermagic.h> #include <linux/compiler.h> MODULE_INFO(vermagic, VERMAGIC_STRING); __visible struct module __this_module __attribute__((section(".gnu.linkonce.this_module"))) = { .name = KBUILD_MODNAME, .init = init_module, #ifdef CONFIG_MODULE_UNLOAD .exit = cleanup_module, #endif .arch = MODULE_ARCH_INIT, }; static const char __module_depends[] __used __attribute__((section(".modinfo"))) = "depends=";
问题根源与修复方案
你的Makefile里多定义了KDIR变量,而且这个变量指向的是内核头文件的include目录,这反而干扰了内核构建系统的默认头文件路径查找逻辑。内核的build目录(也就是/lib/modules/$(shell uname -r)/build/)本身已经包含了正确的头文件路径引用、编译规则等全套配置,完全不需要额外指定KDIR。
修正后的Makefile应该去掉多余的KDIR定义,简化成:
obj-m := hello.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
为什么这样能解决问题?
内核模块的构建依赖于内核官方提供的Kbuild系统,当你执行make -C /lib/modules/$(shell uname -r)/build时,命令会切换到内核的构建目录,那里的顶层Makefile已经帮你配置好了所有必要的头文件搜索路径、编译选项、依赖关系等。你额外定义的KDIR会覆盖或打乱这些默认配置,导致编译器无法正确定位标准内核头文件的位置。
验证步骤
- 把驱动代码里的绝对路径include改回标准形式,比如
#include <linux/init.h>、#include <linux/module.h> - 使用修正后的Makefile执行
make命令 - 编译成功后,用
insmod hello.ko加载模块,再用dmesg | tail查看输出,确认模块正常初始化
这样就能不用写头文件绝对路径,正常编译驱动模块了。
内容的提问来源于stack exchange,提问作者Byers1979

