insmod错误:插入'./hello.ko':-1 无效的模块格式

13

我刚刚做了我的第一个驱动程序模块,是遵循LDD3的hello world模块。然而不幸地遇到了这个错误:

insmod: error inserting './hello.ko': -1 Invalid module format.

我正在使用Ubuntu 11.04进行此操作,并且我的环境为:

$ uname -r
2.6.38-8-generic

我是这样获取内核源代码的:

sudo apt-cache search linux-source
linux-source - Linux kernel source with Ubuntu patches
linux-source-2.6.38 - Linux kernel source for version 2.6.38 with Ubuntu patches
$sudo apt-get install linux-source-2.6.38

我的 /usr/src 目录:

$ls /usr/src/
linux-headers-2.6.38-8          linux-source-2.6.38          vboxguest-5.0.10
linux-headers-2.6.38-8-generic  linux-source-2.6.38.tar.bz2

然后我编译内核

$sudo cp /boot/config-2.6.38-8-generic ./.config
$sudo make menuconfig -- load the .config file
$make
$make modules

然后我编译我的内核模块

$make -C /usr/src/linux-source-2.6.38/linux-source-2.6.38 M=`pwd` modules

使用Makefile:

obj-m := hello.o

最后当我插入模块时:

$sudo insmod hello_world.ko
insmod: error inserting 'hello_world.ko': -1 Invalid module format

我在dmesg中发现的内容:

hello: disagrees about version of symbol module_layout

那么问题是什么?

我还注意到linux-header is -2.26.38-generic,源代码版本为-2.26.38,这是问题吗?但是我在网上真的没有找到linux-source-2.26.38-generic软件包。

状态更新: 我已经发现文件 /lib/moduels/$(name -r)/build/Makefile 显示了我的运行内核版本:

VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 38
EXTRAVERSION = .2

我下载了linux-2.6.38.2并编译,但还是出现了相同的错误。

我还发现在/boot/config-$(uname -r)中有一行:

CONFIG_VERSION_SIGNATURE="Ubuntu 2.6.38-8.42-generic 2.6.38.2"

有人知道这是什么意思吗?我在构建的内核配置文件中没有看到它。


1
insmod 中的错误表明该模块被插入到与其编译时不同的内核中。确保您启动的是与您一直在编译的完全相同的内核... - dragosht
@dragosht,你能指示一下我如何找到我的系统正在运行的确切内核源代码吗?上面的步骤是我在谷歌上找到的,但仍然不起作用。 - roMoon
uname -r 显示已启动的内核,若要选择特定的内核,请在启动时持续按住 Shift 键。 - Rusty
3
请尝试使用以下命令编译您的模块:make -C /usr/src/linux-headers-$(uname -r ) M=pwd modules请注意,该命令旨在在当前目录下编译模块,并需要适当的Linux头文件。 - Rusty
@Rusty,我的系统上'uname -r'显示的是2.6.38-8-generic版本,但是我找不到对应版本为2.6.38-8-generic的内核源代码。我下载的是linux-source-2.6.38.8和linux-source-2.6.38.2,但都无法使用。 - roMoon
显示剩余2条评论
4个回答

12

构建内核模块的内核版本和您要插入模块的版本应该相同。如果您不想担心这件事,可以使用以下Makefile。

obj−m += hello−world.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

现在,您可以构建并尝试插入模块。

我建议在执行以下命令前尽可能以root身份登录:

$sudo cp /boot/config-2.6.38-8-generic ./.config

$su
#cp /boot/config-2.6.38-8-generic ./.config
#insmod hello_world.ko

您也可以使用以下的 makefile。

TARGET  := hello-world
WARN    := -W -Wall -Wstrict-prototypes -Wmissing-prototypes
INCLUDE := -isystem /lib/modules/`uname -r`/build/include
CFLAGS  := -O2 -DMODULE -D__KERNEL__ ${WARN} ${INCLUDE}
CC      := gcc-3.0

${TARGET}.o: ${TARGET}.c

.PHONY: clean

clean:
    rm -rf ${TARGET}.o

东西使用“-C /lib/modules/$(shell uname -r)/build”可以工作,但我真的想知道为什么我编译和运行的内核版本不同。你能给一些提示吗? - roMoon
2
请检查 modinfo hello-world.ko 命令的输出,它会告诉你模块的版本以及所依赖的内核版本。同时,请检查你的内核版本是否与你的模块版本相同。 - Punit Vara
我的内核版本是2.26.38-8-generic,我正在构建模块的内核版本是2.6.38-8。但是我真的找不到内核发布中的2.26.38-8-generic内核源代码。 - roMoon
你是否已经检查了我建议给你的命令?我知道你对自己的内核很了解,但当你使用命令进行检查时,你会发现两个版本是不同的,所以每当你使用$(shell uname -r)时,它都会自动处理这个问题。 - Punit Vara
uname -r 命令会自动从你正在使用的内核头文件构建模块。你不会在任何地方找到这个通用版本。 - Punit Vara
显示剩余5条评论

1
你做的一切都是正确的,但是你没有使用你编译的内核启动系统,所以第一步是你应该用它来启动。 如果你正在使用Ubuntu,你可以在启动时按住Shift键,然后你将会看到一个列出了你系统中已编译内核的列表,从中选择linux-source-2.6.38,然后尝试构建你的模块并按照你的方式安装它,那么你就不会遇到任何问题了。 祝你好运。

1
嗨@Rusty,为什么我必须安装我构建的内核?如果是这样,任何想要安装我的内核的人都必须安装我构建的内核吗? - roMoon

0

尝试使用交叉编译。请查看下面的代码以获取make文件。注意缩进,否则可能会出现错误,例如 missing separator. Stop

obj-m += hello_.o #这个名称应该是您的.c文件的名称。我只是举例使用hello

我建议最好的方法是通过交叉编译

创建一个变量来保存Linux内核目录所在的目录名称。在我的示例中,将值“PATH_TO_LINUX_KERNEL_DIRECTORY”更改为实际路径值 示例~/linux 您真的需要这样做,以便make文件知道在哪里找到arm-linux-gnueabi-。如果没有这个,您可能会遇到问题arm-linux-gnueabi-

KDIR := PATH_TO_LINUX_KERNEL_DIRECTORY

all:
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -C $(KDIR) M=$(shell pwd) modules

clean:
    make -C $(KDIR) M=$(shell pwd) clean

0
请使用以下命令:
sudo apt update && sudo apt upgrade
sudo apt remove --purge linux-headers-*
sudo apt autoremove && sudo apt autoclean
sudo apt install linux-headers-generic

这将重新安装内核头文件


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接