本帖最后由 rt3 于 2021-12-28 22:07 编辑
编译内核模块成功但无法加载:insmod: ERROR: could not insert module ./mymod.ko: Invalid module format
dmesg 的 报错信息:[ 5180.365546] module: x86/modules: Skipping invalid relocation target, existing value is nonzero for type 1, loc 00000000df2a29e3, val ffffffffc14970b6
make 命令:make -C /lib/modules/$(uname -r)/build M=${PWD}
Makefile 文件:ARCH = x86_64
KERN_VER = $(shell uname -r)
KERN_DIR = /lib/modules/${KERN_VER}/build
KBUILD_CFLAGS:= -Wall
EXTRA_CFLAGS += -mcmodel=kernel
obj-m:=mymod.o
module_install:
cp ./mymod.ko /lib/modules/${KERN_VER}
mymod.c:#include <linux/module.h>
#include <linux/timer.h>
#include <linux/errno.h>
static int sec=5;
module_param(sec, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(sec,"Set the interval.");
static void mymod_timer(unsigned long data);
static DEFINE_TIMER(timer,mymod_timer);
static void mymod_timer(unsigned long data) {
printk(KERN_INFO"mymod:timer\n");
mod_timer(&timer, jiffies+sec*HZ);
}
static int mymod_init(void) {
printk(KERN_INFO"mymod:init\n");
if(sec<=0){
printk(KERN_INFO"Invalid interval sec=%d\n",sec);
return-EINVAL;
}
mod_timer(&timer, jiffies+sec*HZ);
return 0;
}
static void mymod_exit(void){
del_timer(&timer);
printk(KERN_INFO"mymod:exit\n");
}
module_init(mymod_init);
module_exit(mymod_exit);
MODULE_AUTHOR("Hiroshi Shimamoto");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("My module");
内核版本:
5.15.11-200.fc35.x86_64
thx
我弄明白了,先说一下出问题的原因
因为你现在正在运行的内核和你编译内核模块用的内核源码不匹配
也就是说Makefile一定是要用这个 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
我试了,我下载了一个内核源码,用这个源码来编译内核模块
可以生成 hello.ko 文件,但是不能用 insmod 载入内核执行,报错信息和你的一样
也就是说你要把编译生成的内核模块载入当前正在运行的这个内核执行
编译内核模块的时候必须要使用和当前正在运行的这个内核匹配的内核源码
在我这边,这个和当前正在运行的内核匹配的内核源码放在这里
安装好系统以后就放在这里了,是安装脚本放在这里的 /lib/modules/$(shell uname -r)/build
你可能会说,你找不到和当前正在运行的这个内核匹配的内核源码
没关系,下载一个内核源码,编译生成内核,然后运行生成的这个内核
这样就有了匹配的内核源码了
这个方法我也试了,没问题
这里说一下需要注意的几点
vmlinuz-linux 和 initramfs-linux.img 这两个文件放在哪里都无所谓
但是内核模块必须放在这个目录下面
因为你新编译的内核和现在正在运行的内核的版本应该是不一样吧,所以不会冲突
这个目录下面,一个内核版本对应一个目录
vmlinuz-linux 就是 bzImage
这个文件在内核源码的这个目录下面,把 bzImage 的名字改成 vmlinuz-linux 也行
不改也可以,无所谓
这个目录 $ ls arch/x86/boot/bzImage
arch/x86/boot/bzImage
$
还有,这个文件必须重新生成,不能使用boot目录下面的那个
initramfs-linux.img
开机的时候用grub命令手动引导新内核
当然你可以配置grub自动引导新内核,这也无所谓
如果你打算一直使用这个新内核的话
我就不打算一直使用新编译的这个内核,我就是试了试
我这边把 bzImage 和 initramfs-linux.img 放在了 /mnt/sdc1/boot 下面
大概就这些
|