问题
写了个简单的模块demo
#include <linux/kernel.h>
#include <linux/module.h>
static int __init demo_init(void)
{
return 0;
}
static void __exit demo_exit(void)
{
}
module_init(demo_init)
module_exit(demo_exit)
MODULE_LICENSE("GPL");
Makefile内容
obj-m := demo.o
KDIR := /usr/src/kernels/$(shell uname -r)/
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.mod* *.ko *.o *.order *.symvers .*.cmdclean:
make -C $(KDIR) M=$(PWD) clean
编译
[root@root demo]# make
make -C /usr/src/kernels/5.14.0-331.el9.x86_64/ M=/root/demo modules
make[1]: Entering directory '/usr/src/kernels/5.14.0-331.el9.x86_64'
CC [M] /root/demo/demo.o
MODPOST /root/demo/Module.symvers
CC [M] /root/demo/demo.mod.o
LD [M] /root/demo/demo.ko
BTF [M] /root/demo/demo.ko
Skipping BTF generation for /root/demo/demo.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/kernels/5.14.0-331.el9.x86_64'
然后 insmod demo.ko
报错 invalid format,查看内核消息查看具体报错。
[root@root demo]# insmod demo.ko
insmod: ERROR: could not insert module ./mymod.ko: Invalid module format
[root@root demo]# dmesg
....
[ 1498.202829] module: x86/modules: Skipping invalid relocation target, existing value is nonzero for type 1, loc 00000000df2a29e3, val ffffffffc14970b6
问题原因分析
使用的系统环境 centos 9.3,在编译模块前,我有运行过以下三条指令,检查发现,他们会安装最新的版本,而不是和我系统对应的版本,尝试 yum install "kernel-devel-uname-r == $(uname -r)"
发现centos9.3已经不支持,我的 uname -r
是5.14.0-331.el9.x86_64,检查/usr/src/kernels/5.14.0-331.el9.x86_64/也存在,版本是对上的,那为什么加载失败,猜测是下面的指令导致某些软件版本没有对应好。
yum install kernel-devel
yum install kernel-headers
yum install glib-static
解决办法
尝试升级系统和系统软件,升级完成后,重启,再次尝试编译(注意修改Makefile中KDIR为升级后的内核源码路径)、加载模块,完美解决问题。
yum upgrade
yum install kernel-devel
yum install kernel-headers