【问题标题】:Why would a Linux kernel module symbol not be exported globally properly?为什么不能正确全局导出 Linux 内核模块符号?
【发布时间】:2016-01-25 07:16:20
【问题描述】:

我们编写了许多内核模块,其中许多带有导出的符号,除了 2 个符号(令人费解)之外,它们都可以正常工作。我们已将它们与其他所有符号一样导出,但是这两个符号在插入内核后不会全局导出。

在我们的 C 代码中(在 wdt.ko 中):

EXPORT_SYMBOL(WDT_Enable);
EXPORT_SYMBOL(WDT_Disable);

如果我们在生成的内核对象上运行nm,它们会正确显示:

nm wdt.ko | grep WDT
00000000 T WDT_Enable
00000000 T WDT_Disable

这应该意味着这些符号是全局导出的。一旦我们 insmod 内核对象:

# insmod wdt.ko
# insmod apphandler.ko
apphandler: Unknown symbol WDT_Enable
apphandler: Unknown symbol WDT_Disable

如果我们看一下 kallsyms:

# cat /proc/kallsyms | grep WDT
c12504dc t WDT_Enable  [wdt]
c12502d8 t WDT_Disable [wdt]

一旦它们进入内核,它们就不是全局的。

我们已经确认将正确的文件插入内核并且函数在同一个模块中可见,但我们无法解释为什么这些符号突然变成局部而不是像nm 建议的那样全局。

有人知道我们的错误可能在哪里吗?

【问题讨论】:

  • nm/proc/kallsyms 显示的全局可见性,并不意味着其他模块的可用性,由@987654331 控制@,见例如这个answer。此外,对于由一个模块定义的 make 符号在另一个模块中可用,仅EXPORT_SYMBOL 是不够的。您需要在同一目录中构建两个模块,或者在第二个模块的 makefile 中使用 KBUILD_EXTRA_SYMBOLS 变量:stackoverflow.com/a/32949236/3440745
  • 是的 - 同意您的 cmets,并且如前所述,我们的其他符号都在工作。我们定义 WDT 的一个 C 文件不包括下面的头文件。我们确实在同一个地方构建了所有模块,并且每个模块都有一个“通用”构建文件模板。

标签: c linux linux-kernel insmod


【解决方案1】:

好的 - 在发布问题后不久,我们注意到我们的包含路径缺少模块包含:

#include <linux/module.h>

代码似乎编译文件时没有包含#include,编译器没有产生错误或投诉,但最终结果是后续模块无法使用这些符号。

由于包含头文件,上述符号可用于模块,内核能够解析和执行代码。

【讨论】:

  • 将此信息添加到您的问题帖子中(通过编辑),而不是将其作为答案发布(因为它实际上不是答案)。
  • 不幸的是,它确实解决了我们的问题。我无法真正解释为什么省略标题会导致效果,但包含它会使符号按照宣传的方式执行。除了#include 之外,没有进行其他更改
  • 由于额外的重新编译周期,它可能会起作用。尝试删除并复制。
  • 如果这个修改解决了问题,but had the above effect是什么意思?
  • 在这个问题之前有很多很多很多很多的重新编译周期,以及删除、恢复、还原等。上述效果无法使符号可用(即 insmod 错误)。在#include 之后,模块正确插入,函数调用正确。
猜你喜欢
  • 1970-01-01
  • 2012-04-21
  • 2020-02-16
  • 2011-02-12
  • 2012-02-26
  • 2020-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多