正确编译最简内核模块需用内核构建系统:写makefile含obj-m += hello.o和$(make) -c /lib/modules/$(shell uname -r)/build m=$(pwd) modules,并确保已安装对应linux-headers。

怎么用 make 正确编译一个最简内核模块
内核模块不能像普通程序那样直接 gcc 编译,必须复用内核构建系统。最简可行路径是写一个 Makefile,内容只有两行:
obj-m += hello.o<br>$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules注意
/lib/modules/$(shell uname -r)/build 必须指向已安装的内核头文件目录(不是源码目录),否则会报 No rule to make target 'scripts/Makefile.build'。如果系统没装 linux-headers-$(uname -r),先装它。
insmod 失败常见报错和对应解法
报 Invalid module format:模块编译时用的内核版本和当前运行内核不一致,检查 uname -r 和 /lib/modules/ 下目录名是否完全匹配;报 Unknown symbol in module:模块用了未导出的内核符号(比如 __kmalloc),改用 kmalloc 等导出函数;报 Operation not permitted:SELinux 或者 secure boot 启用中,临时关 SELinux 用 setenforce 0,secure boot 需要签名或禁用。
为什么 modprobe 找不到你的模块
modprobe 默认只在 /lib/modules/$(uname -r)/kernel/ 及子目录下搜索,不会看当前路径。要把模块复制过去并更新索引:
sudo cp hello.ko /lib/modules/$(uname -r)/extra/<br>sudo depmod -a注意路径必须是
extra/ 或 updates/ 这类被 depmod 扫描的子目录;如果模块有依赖,得在 .ko 同目录放 modules.alias 或靠 MODULE_LICENSE 宏让内核识别许可状态。
加载后怎么确认模块真在跑、没悄悄挂掉
别只信 insmod 没报错——它成功返回不代表初始化函数没崩。用 dmesg | tail -20 看内核日志,模块的 printk 输出和 init_module 返回值会在这里体现;用 lsmod | grep hello 确认模块名出现在列表里;卸载前务必确保没进程或设备在用它,否则 rmmod 会卡住或报 Device or resource busy。模块里没写 module_exit 函数也能加载,但无法安全卸载。










