bug1:Module.symvers 缺失

本文介绍了解决在编译Linux内核模块时遇到的Module.symvers缺失问题的方法,通过下载对应版本的内核头文件并执行make oldconfig、make prepare及make scripts命令来修复编译错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编译linux2.2.37内核模块时候

"Module.symvers is missing"



解决办法:

在linux内核下面执行:(中间加上编译器)

make  oldconfig 

 make  prepare

make  scripts




原因:通常头核心包中是没有Module.symvers这个文件的,要想获取这个文件只能到下载相同版本核心(2.6.26-1-686)的头文件,是下载不是apt-get install  !!!,只有下载的头文件中才有这个Module.symvers。把Module.symvers 复制到核心包中,然后执行如下步骤:make oldconfig && make prepare && make scripts。
然后重新编译驱动,将解决这个warning,同时也解决了版本不正确的问题


运行:make -C /usr/src/linux-2.6.34-12 SUBDIRS=$PWD modules
出错如下:

make: Entering directory `/usr/src/linux-2.6.34-12'

  ERROR: Kernel configuration is invalid.
         include/generated/autoconf.h or include/config/auto.conf are missing.
         Run 'make oldconfig && make prepare' on kernel src to fix it.

 WARNING: Symbol version dump /usr/src/linux-2.6.34-12/Module.symvers
           is missing; modules will have no dependencies and modversions.

scripts/Makefile.build:44: /usr/src/linux-2.6.34-12/PWD/Makefile: No such file or directory
make[1]: *** No rule to make target `/usr/src/linux-2.6.34-12/PWD/Makefile'.  Stop.
make: *** [_module_PWD] Error 2
make: Leaving directory `/usr/src/linux-2.6.34-12'




运行:make oldconfig && make prepare

再次出错如下:

 

make: Entering directory `/usr/src/linux-2.6.34-12'

  WARNING: Symbol version dump /usr/src/linux-2.6.34-12/Module.symvers
           is missing; modules will have no dependencies and modversions.

  CC [M]  /home/xxx/test/dr/drhello.o
  Building modules, stage 2.
  MODPOST 1 modules
/bin/sh: scripts/mod/modpost: No such file or directory
make[1]: *** [__modpost] Error 127
make: *** [modules] Error 2
make: Leaving directory `/usr/src/linux-2.6.34-12'



加上:make scripts

可以了

 

make: Entering directory `/usr/src/linux-2.6.34-12'

  WARNING: Symbol version dump /usr/src/linux-2.6.34-12/Module.symvers
           is missing; modules will have no dependencies and modversions.

  CC [M]  /home/xxx/test/dr/drhello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/test/dr/drhello.mod.o
  LD [M]  /home/test/dr/drhello.ko
make: Leaving directory `/usr/src/linux-2.6.34-12'





<think>我们正在解决Linux内核模块编译时出现的"undefinedsymbol"错误。根据引用[1]和[3],这个问题通常是由于模块之间的符号依赖关系没有正确解析导致的。具体来说,当模块B(caller)使用了模块A(exporter)导出的符号(函数或变量),而模块B在编译时没有获取到模块A的符号版本信息,就会在加载时出现"undefinedsymbol"错误。解决方案的核心是让模块B在编译时能够获取到模块A的符号信息。这可以通过以下步骤实现:1.在编译模块A(导出符号的模块)后,将其生成的`Module.symvers`文件复制到模块B的源代码目录中,或者2.在模块B的Makefile中,通过`KBUILD_EXTRA_SYMBOLS`变量指定模块A的`Module.symvers`文件的路径(绝对路径)。引用[1]中提到,这是Linuxkernel2.6.26之后版本的一个已知bug,并且不会修复。因此,我们必须采用上述方法。具体操作步骤如下:###步骤1:编译导出符号的模块(模块A)进入模块A的源代码目录,执行编译:```bashmake-C/lib/modules/$(uname-r)/buildM=$(pwd)modules```编译完成后,在模块A的目录下会生成`Module.symvers`文件。这个文件包含了模块A导出的符号及其版本信息。###步骤2:将模块A的符号信息提供给模块B有两种方法:####方法一:复制`Module.symvers`文件将模块A的`Module.symvers`文件复制到模块B的源代码目录中:```bashcp/path/to/module_a/Module.symvers/path/to/module_b/```然后编译模块B:```bashmake-C/lib/modules/$(uname-r)/buildM=$(pwd)modules```####方法二:在Makefile中指定`KBUILD_EXTRA_SYMBOLS`(推荐)在模块B的Makefile中,添加(或修改)`KBUILD_EXTRA_SYMBOLS`变量,指向模块A的`Module.symvers`文件(使用绝对路径):```makefileKBUILD_EXTRA_SYMBOLS:=/path/to/module_a/Module.symvers```然后编译模块B。###步骤3:加载模块注意加载顺序:先加载模块A,再加载模块B。```bashsudoinsmodmodule_a.kosudoinsmodmodule_b.ko```###补充说明-如果模块A和模块B在同一目录下编译,且模块A先编译,那么模块B在编译时可能会自动找到模块A的`Module.symvers`(因为编译系统会在当前目录查找)。但为了确保,建议使用上述方法之一。-如果模块A的符号发生变化(比如增加了新的导出函数),需要重新编译模块A,并更新其`Module.symvers`,然后重新编译模块B。###示例Makefile(模块B)假设模块B的Makefile原本如下:```makefileobj-m:=module_b.oall:make-C/lib/modules/$(shelluname-r)/buildM=$(PWD)modulesclean:make-C/lib/modules/$(shelluname-r)/buildM=$(PWD)clean```修改后,添加`KBUILD_EXTRA_SYMBOLS`(注意:这个变量需要在`make`命令执行前设置,因此可以直接在Makefile中设置):```makefileobj-m:=module_b.o#设置额外的符号表路径(使用绝对路径)KBUILD_EXTRA_SYMBOLS:=/absolute/path/to/module_a/Module.symversall:make-C/lib/modules/$(shelluname-r)/buildM=$(PWD)modulesclean:make-C/lib/modules/$(shelluname-r)/buildM=$(PWD)clean```###验证加载模块后,可以使用`dmesg`查看内核日志,确认模块B是否正确调用了模块A的函数(如引用[4]中的示例输出)。###其他可能的问题-如果模块A和模块B编译时使用的内核版本不一致,也会导致符号不匹配。确保两个模块都在同一内核版本下编译(引用[2]提到更新内核头文件的方法,但这里我们不需要更新,只需确保一致)。-如果模块A没有导出模块B需要的符号,需要检查模块A的导出符号(使用`EXPORT_SYMBOL`或`EXPORT_SYMBOL_GPL`),并确保模块B声明了外部符号(使用`extern`)。通过以上步骤,应该可以解决"undefinedsymbol"错误。§§相关问题§§1.如何在Linux内核模块中导出符号供其他模块使用?2.如何查看一个内核模块导出了哪些符号?3.内核模块的版本控制(MODVERSION)是如何工作的?4.如何解决内核模块加载时的版本不匹配问题?5.什么是`Module.symvers`文件,其格式是怎样的?</think>### Linux内核模块"undefined symbol"错误解决方案 当编译Linux内核模块遇到"undefined symbol"错误时,通常是由于模块间符号依赖未正确解析导致的。以下是系统化的解决方法: #### 1. **理解问题本质** - **错误原因**:模块B调用模块A导出的函数/变量,但编译时未获取模块A的符号版本信息 - **核心机制**:内核使用CRC校验确保符号兼容性,缺少校验码导致加载失败[^1] - **错误示例**: ``` Unknown symbol in module: function_name (err -2) ``` #### 2. **标准解决方案:使用Module.symvers** ##### 步骤1:编译导出模块(模块A) ```bash cd /path/to/module_a make -C /lib/modules/$(uname -r)/build M=$(pwd) modules ``` 生成关键文件:**Module.symvers**(包含符号校验信息) ##### 步骤2:配置调用模块(模块B)的Makefile ```makefile # 在模块B的Makefile中添加: KBUILD_EXTRA_SYMBOLS := /absolute/path/to/module_a/Module.symvers ``` ⚠️ **必须使用绝对路径**(相对路径会导致解析失败)[^3] ##### 步骤3:重新编译依赖模块 ```bash cd /path/to/module_b make clean make -C /lib/modules/$(uname -r)/build M=$(pwd) modules ``` #### 3. **替代方案:符号表合并** ```bash # 将多个模块的符号表合并 cat module_a/Module.symvers module_c/Module.symvers > combined.symvers export KBUILD_EXTRA_SYMBOLS=$(pwd)/combined.symvers make -C /lib/modules/$(uname -r)/build M=$(pwd) modules ``` #### 4. **验证符号导出** ```bash # 检查模块导出的符号 nm module_a.ko | grep EXPORT_SYMBOL # 查看符号CRC校验码 grep 'symbol_name' Module.symvers ``` #### 5. **高级场景处理** | 场景 | 解决方案 | |------|----------| | 循环依赖 | 使用`combined.symvers`合并所有依赖 | | 跨内核版本 | 确保所有模块在同一内核版本编译[^2] | | 动态加载 | 使用`request_module("dependency")`运行时加载 | #### 6. **内核配置优化** 在`/usr/src/linux/.config`中启用: ```config CONFIG_MODVERSIONS=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y ``` #### 7. **调试技巧** ```bash # 查看未解析符号 dmesg | grep "undefined" # 检查符号版本 modprobe --dump-modversions module.ko ``` > **加载顺序**:始终先加载导出模块(A),再加载依赖模块(B)[^4] > ```bash > sudo insmod module_a.ko > sudo insmod module_b.ko > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值