尝试加载usbhid.ko时“没有module_layout的符号版本”

我正在尝试为usbhid.ko构建我自己的模块,但在编译之后,我无法加载模块。 dmesgno symbol version for module_layout 。 我想知道是什么问题? 我已经使用了Ubuntu提供的内核源代码,我也确保内核版本是一样的。

具体问题是,当您构建模块时,内核源代码树可能缺少Modules.symvers文件。 在构建模块时,kbuild系统实际上会警告您。 如果缺少Modules.symvers,您将看到:

警告:缺少符号版本转储/usr/src/linux-2.6.34-12/Modules.symvers; 模块没有依赖关系和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  

我倾向于选择2 🙂

安装与您的内核相对应的linux-headerslinux-source包。 例如,对于内核3.2.0-27-generic-pae您需要:

  1. linux-headers-3.2.0-27-generic-pae
  2. linux-source-3.2.0-27-generic-pae

如果上述软件包的版本与正在运行的内核版本不匹配,则需要将$(uname -r)替换$(uname -r)上面安装的内核软件包中的版本字符串。
对于上面的示例,包版本是3.2.0-27-generic-pae 当您运行uname -r并且其输出与3.2.0-27-generic-pae您需要替换下面的每个$(uname -r)以匹配已安装软件包中的版本字符串。

  1. cd /usr/src/linux-source-$Version并解压缩.tar.bz2存档并cd到解压缩的目录中 – 我想你已经这样做了
  2. cp /boot/config-$(uname -r) .config进入内核源目录
  3. cp /usr/src/linux-headers-$(uname -r)/Module.symvers . 进入内核源目录

完成后,在内核源目录中,执行以下操作:

  1. make prepare
  2. make scripts
  3. make M=drivers/usb/serial – 在M=之后改变路径以满足您的需要

不幸的是,我不知道如何在保持Module.symvers不变的情况下构建特定模块。 例如, make drivers/usb/serial/option.ko杀死Module.symvers文件,最终会遇到原始问题。 使用M=参数不会杀死它,但你必须在指定的路径中构建所有模块 – 我还没有找到解决方法。

在运行make prepare之前,必须使用完全相同的内核配置。 此外,如果您在树外构建它,则需要针对与当前运行的内核(或者如果您在编译时未运行它)匹配的目标内核头完全相同的内核头构建它。