已安装内核头文件,编译Linux驱动模块仍提示linux/init.h不存在怎么办
问题解决步骤
错误根源
直接使用gcc编译内核模块不会自动关联内核头文件搜索路径,你安装的内核头文件存放在/lib/modules/$(uname -r)/build/include目录下,不属于用户态gcc默认的头文件搜索路径,所以会找不到linux/init.h。内核模块必须使用内核源码树提供的编译架构进行编译,不能手动调用普通gcc命令。
步骤1:修正驱动代码
现有代码有两个必须修复的问题:
hello_init函数声明返回int类型,缺少返回语句- 缺少
MODULE_LICENSE声明,后续加载模块会触发内核警告
修正后的完整代码(假设文件名为hello.c):
#include <linux/init.h> #include <linux/module.h> static int hello_init(void) { printk(KERN_ALERT, "Hello world\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT, "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL");
步骤2:编写内核模块专用Makefile
在同一目录下创建名为Makefile的文件,内容如下:
注意:Makefile中
make开头的行必须用Tab缩进,不能用空格
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
这个Makefile会调用内核源码树自带的编译架构,自动配置头文件搜索路径、编译参数、宏定义等内核模块必须的编译规则。
步骤3:执行编译
直接在当前目录执行make命令即可,不要手动调用gcc:
make
编译完成后会生成hello.ko内核模块文件,可使用sudo insmod hello.ko加载模块,dmesg查看内核打印输出,sudo rmmod hello卸载模块。
其他注意事项
- 如果执行make时报头文件路径不存在的错误,先确认是否更新过内核但未重启,重启后内核版本和已安装的头文件版本匹配即可解决
- 不要用
-I参数手动给gcc加内核头文件路径,手动配置编译参数很容易出现各类兼容问题
内容的提问来源于stack exchange,提问作者victor 0x3E7
相关产品推荐
相关产品推荐

