警告:构建使用导出符号的内核模块

8

我有两个内核模块(称为modA和modB)。modA使用EXPORT_SYMBOL(symA)导出一个符号,而modB使用它。我有modA的头文件modA.h

...
extern void symA(int param);
...

还有在modB.c文件中:

#include "modA.h"
...
static int __init modB_init(void)
{
    symA(10);
}
...

如果我使用 insmod 命令加载 modB,一切正常,我的 modB 在内核中正确链接,并且函数 symA 被正确调用。然而,当我构建 modB 时,编译器会发出警告: symA 未定义。LKM 是可重定位的 ELF 文件,为什么编译器会发出这个警告?如何消除这个警告?
1个回答

12

这个问题(以及如何在这种情况下正确编译)在http://www.kernel.org/doc/Documentation/kbuild/modules.txt中有详细解释。

有时,一个外部模块会使用另一个外部模块导出的符号。为了避免出现未定义符号的警告,kbuild需要完全了解所有符号。针对这种情况,有三个解决方案。

注意:使用顶层 kbuild 文件的方法是推荐的,但在某些情况下可能不可行。

使用顶层 kbuild 文件 如果你有两个模块 foo.ko 和 bar.ko,其中 foo.ko 需要来自 bar.ko 的符号,你可以使用一个通用的顶层 kbuild 文件,这样两个模块都将在同一构建中编译。考虑以下目录布局:

  ./foo/ <= contains foo.ko       ./bar/ <= contains bar.ko

  The top-level kbuild file would then look like:

  #./Kbuild (or ./Makefile):          obj-y := foo/ bar/

  And executing

      $ make -C $KDIR M=$PWD

  will then do the expected and compile both modules with         full

从任一模块中获取符号的知识。

使用额外的 Module.symvers 文件 当构建外部模块时,会生成一个 Module.symvers 文件, 其中包含所有未在内核中定义的导出符号。要访问来自 bar.ko 的符号,请将 bar.ko 的 Module.symvers 文件复制到构建 foo.ko 的目录中。 在模块构建期间,kbuild 将读取外部模块所在目录中的 Module.symvers 文件,完成构建后,将创建一个新的 Module.symvers 文件, 其中包括所有已定义但不属于内核的符号的总和。

使用“make”变量 KBUILD_EXTRA_SYMBOLS 如果从另一个模块拷贝 Module.symvers 不现实, 您可以在构建文件中为 KBUILD_EXTRA_SYMBOLS 分配一个以空格分隔的文件列表。这些文件将在 modpost 初始化其符号表时被加载。


太好了!我错过了那个。谢谢Gossamer! - MirkoBanchi

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