问题描述
我正在尝试为usbhid.ko
构建自己的模块,但是在编译之后,无法加载该模块。 dmesg
说是no symbol version for module_layout
。我想知道是什么问题?我已经使用过Ubuntu提供的内核源代码,并且还要确保内核版本相同。
最佳回答
具体来说,问题是在构建模块时,内核源代码树可能缺少Modules.symvers文件。当您构建模块时,kbuild系统实际上会警告您。如果缺少Modules.symvers,您将看到:
Warning: Symbol version dump /usr/src/linux-2.6.34-12/Modules.symvers is missing; modules will have no dependencies and modversions.
如果您的内核启用了CONFIG_MODVERSIONS
,则在构建驱动程序的modpost阶段,它将使用-m选项运行scripts /mod /modpost。如果您勇敢地看一下scripts /mod /modpost.c源代码,您会看到-m选项添加了vmlinux中的_module_layout_符号,但是,如果您的内核中没有Modules.symvers,您将无法获得该符号的CRC值,并最终收到此错误消息。
因此,有两种解决方法。
1)运行正在运行的内核的完整版本以生成Modules.symvers,然后重新构建模块。 [http://www.mjmwired.net/kernel/Documentation/kbuild/modules.txt][1]
51 === 2. How to Build External Modules
52
53 To build external modules, you must have a prebuilt kernel available
54 that contains the configuration and header files used in the build.
55 Also, the kernel must have been built with modules enabled. If you are
56 using a distribution kernel, there will be a package for the kernel you
57 are running provided by your distribution.
58
59 An alternative is to use the "make" target "modules_prepare." This will
60 make sure the kernel contains the information required. The target
61 exists solely as a simple way to prepare a kernel source tree for
62 building external modules.
63
64 NOTE: "modules_prepare" will not build Module.symvers even if
65 CONFIG_MODVERSIONS is set; therefore, a full kernel build needs to be
66 executed to make module versioning work.
2)另一个选择是让愚蠢的modprobe忽略所有的废话,反正只是加载模块:
modprobe -f <module>
我倾向于选择选项2 🙂
次佳回答
同时安装与您的内核相对应的linux-headers
和linux-source
软件包。例如,对于内核3.2.0-27-generic-pae
,您需要:
-
linux-headers-3.2.0-27-generic-pae
和 -
linux-source-3.2.0-27-generic-pae
。
如果以上软件包的版本与您正在运行的内核版本不匹配,那么您需要使用上面安装的内核软件包中的版本字符串替换$(uname -r)
。对于以上示例,软件包版本为3.2.0-27-generic-pae
。当您运行uname -r
时,其输出与3.2.0-27-generic-pae
有所不同,那么您需要替换下面的每个$(uname -r)
,以匹配已安装软件包中的版本字符串。
-
cd /usr/src/linux-source-$Version
并将.tar.bz2存档解压缩到位,并将cd放入提取的目录中-我想您已经做到了 -
cp /boot/config-$(uname -r) .config
进入内核源目录 -
cp /usr/src/linux-headers-$(uname -r)/Module.symvers .
进入内核源目录
完成之后,在内核源目录中执行以下操作:
-
make prepare
-
make scripts
-
make M=drivers/usb/serial
-在M=
之后更改路径以适合您的需求
不幸的是,我不知道如何构建特定的模块,同时又保持Module.symvers
不变。例如,执行make drivers/usb/serial/option.ko
会杀死Module.symvers
文件,您最终会遇到原来的问题。使用M=
参数不会杀死它,但是您必须在指定的路径中构建所有模块-而且我还没有找到解决它的方法。