我有这个嵌入式 Linux 设备。我想向它添加内核级功能,但非常希望不编译我自己的内核来这样做。(如果内核没有加载并进入用户空间,设备就会变砖;我无法访问引导加载程序来恢复它。当前的内核没有 kexec 支持,所以我不能用它来测试内核映像我自己的。)
设备的内核支持模块,但我没有相应的 Module.symvers 文件的副本。
我的问题:如果我没有 Linux 内核的 Module.symvers 文件,但确实有内核映像和为其编译的模块,我是否可以编译更多可以插入该内核的模块,也许是通过生成缺少的模块。 symvers 文件?
该设备运行 Linux 内核版本 3.10。
内核映像(在其 uImage 容器中) : https
://www.olio.watch/olio-firmware-1.10.220/olio-firmware/uImage配置(由于 CONFIG_IKCONFIG 从上图中提取):https://www.olio .watch/3.10.0-g2ae2f33-config
我拥有的一个与该内核匹配的内核模块:https ://www.olio.watch/olio-firmware-1.10.220/olio-firmware/drv2605.ko
首先,为了回答您的问题“我可以在没有 Module.symvers 的情况下编译 Linux 内核模块吗”,我们需要了解的目的是什么
Module.symvers
:Module.symvers
有两个主要目的:1) 它列出了从 vmlinux 和所有模块导出的所有符号。
CONFIG_MODVERSIONS
2) 如果启用,它会列出 CRC 。如果不CONFIG_MODVERSIONS
启用,CRC 将读取 0x00000000。Module.symvers
将在内核构建期间生成,它包含从内核和编译模块导出的所有符号。对于每个符号,还存储相应的 CRC 值。Module.symvers 文件的语法是:例如:
话虽如此,如果我们有
Module.symvers
那么我们可以构建任何模块,因为它包含所有必要的符号。如果
Module.symvers
不可用,我们仍然可以通过构建此文件或从另一个模块借用它来构建外部模块。通常,在构建外部模块时,构建系统需要访问内核中的符号以检查是否定义了所有外部符号。这是在一个名为
MODPOST
.Module.symvers
此步骤通过从内核源代码树中读取来获取符号。如果
Module.symvers
正在构建外部模块的目录中存在文件,则该文件也将被读取。在该MODPOST
步骤中,Module.symvers
将写入一个新文件,其中包含所有未在内核中定义的导出符号。如果
Module.symvers
文件不存在,则外部模块可能正在使用从另一个外部模块导出的符号,kbuild
需要完全了解所有符号以避免吐出有关未定义符号的警告。对于这种情况,有三种解决方案:
1) 使用顶级
kbuild
文件:如果您有两个模块,foo.ko
并且bar.ko
需要foo.ko
来自 的符号bar.ko
,您可以使用一个通用的顶级kbuild
文件,以便在同一个构建中编译两个模块。考虑以下目录布局:2) 使用额外
Module.symvers
文件:当构建外部模块时,Module.symvers
会生成一个文件,其中包含所有未在内核中定义的导出符号。要从 中访问符号bar.ko
,请将 Module.symvers 文件从 bar.ko 的编译中复制到构建 foo.ko 的目录中。在模块构建期间,kbuild
将读取Module.symvers
外部模块目录中的文件,当构建完成时,将Module.symvers
创建一个新文件,其中包含所有已定义符号的总和,而不是内核的一部分。3)使用“make”变量
KBUILD_EXTRA_SYMBOLS
:如果从另一个模块复制不切实际,您可以在构建文件中Module.symvers
分配一个以空格分隔的文件列表。KBUILD_EXTRA_SYMBOLS
这些文件将modpost
在其符号表初始化期间加载。更多详情1