【发布时间】:2013-02-12 14:06:54
【问题描述】:
想象一个项目,需要构建两个 linux 内核模块,源码树布局如下:
modules/
|--common/
| `--common_data.c
|--mod1/
| `--mod1_main.c
`--mod2/
`--mod2_main.c
common_data.o 目标文件需要包含在两个模块中。所以这个项目的 Kbuild 文件看起来像这样:
obj-m := mod1.o mod2.o
mod1-y := mod1/mod1_main.o common/common_data.o
mod2-y := mod2/mod2_main.o common/common_data.o
如果 common_data.c 文件中没有导出符号(即 EXPORT_SYMBOL),则构建良好。但是,如果有一些导出的符号(例如some_func),那么 MODPOST 将产生如下警告:
WARNING: mod2: 'some_func' exported twice. Previous export was in mod1.ko
这是因为两个模块共享一个 Module.symvers 文件。可以在 mod1/ 和 mod2/ 目录中创建两个单独的 Kbuild 文件以避免出现此警告,因为这样就会有两个单独的 Module.symvers 文件。但这会导致另一个问题 - commond_data.o 对象将被构建两次 - 第一次是在编译 mod1.ko 时,第二次是在编译 mod2.ko 时。
有什么方法可以在使用单个 Kbuild 文件时抑制此警告,或者在使用两个单独的 Kbuild 文件时防止第二次重建 common_data.o 文件?
【问题讨论】:
-
如果两个模块都导出相同的符号名称,则不可能同时将两个模块插入内核。那是你要的吗?通常,通用功能,例如您导出的符号,将被分解到它自己的模块中。
-
是的,我知道不可能同时插入它们,但这不是必需的。在我的情况下 mod1 和 mod2 是故意以这种方式设计的。基本上,mod2 是相同的 mod1 模块,但具有一些附加功能(例如单元测试)。
-
@AustinPhillips 我也有同样的情况,但我有点犹豫是否要简单地忽略这些消息而不了解它们为什么会发生。警告消息是否纯粹是警告(即只是警告您一次只能加载其中一个模块)?
-
@VilhelmGray 是的,它们只是一个警告。插入模块时,就像生成二进制文件时的链接步骤一样,所有符号都被解析为地址。与正常链接步骤一样,您不能链接具有相同符号的两个不同目标文件。内核符号命名空间是全局的,因此它只是试图警告您其他人使用了该全局名称。