缺少具有多个源文件的内核模块中的组件

时间:2011-09-20 18:40:05

标签: module linker linux-kernel

我有一个带有单个C源文件foo.c的小模块,一切都很顺利。

#include <linux/init.h>
#include <linux/module.h>
static int __init foo_init(void) {
        printk(KERN_INFO "foo_init says hello (%d)\n");
        return 0;
}
static void __exit foo_exit(void) {
}
module_init(foo_init);
module_exit(foo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ACME");

Makefile很简单:

obj-m += foo.o

现在源已经增长,我想添加第二个源文件bar.c

#include <linux/init.h>
#include <linux/module.h>
int aux(int x) {
        return x + 1;
}

我已在aux中添加了对foo.c功能的调用。 (好吧,在现实生活中,我在标题中声明了aux函数,而我的代码不仅仅是打印一条消息,而是我将问题缩小到这个小例子。)我添加了一行代码在Documentation/kbuild/makefiles.txt之后,在makefile中声明模块的组件。

foo-objs += bar.o
obj-m += foo.o

但是现在,当我构建模块时,foo.o似乎没有链接(modinfo报告没有模块许可证和作者,nm foo.ko找不到foo.c中定义的符号{1}},foo_init在加载模块时显然没有运行。将foo-objs := foo.o bar.o放在makefile中没有用。

为什么添加第二个源文件会替换第一个源文件,以及如何获取foo

如果这很重要:内核版本是2.6.35,架构是arm,模块是in-tree。

2 个答案:

答案 0 :(得分:3)

为了让你的东西能够编译,我建议你将foo.c重命名为例如foo-base.c(我的想法是不要让.c文件与模块同名。foo-objs将根据您指定的其他对象构建foo.o不是来自foo.c

然后你可以这样做:

foo-objs := foo-base.o bar.o
obj-m += foo.o

foo-y := ...也有效,但我看过的Makefiles使用-objs版本。)
它应该工作:

$ modprobe foo
$ dmesg|tail
...
[ 8375.303738] foo_init says hello (100)
$ modinfo foo
filename:       /lib/modules/3.0.3-gentoo/kernel/drivers/usb/test/foo.ko
author:         ACME
license:        GPL
depends:        
vermagic:       3.0.3-gentoo SMP mod_unload 

[也就是说,在你的样本中给printk提供了足够的论据之后: - )]

注意:在更改后重建模块之前,请不要忘记清理所有生成的文件。

答案 1 :(得分:0)

缩小到一个小例子是解决这个问题的90%。它让我看到,在makefile中foo-objs := foo.o bar.omake抱怨:

make[1]: Circular z/foo.o <- z/foo.o dependency dropped.

使用foo-objs += bar.o更难以发现问题,但它隐藏在make V=1的输出中:

ld -EL    -r -o z/foo.o z/bar.o

幕后发生的事情是$(module_name).o$(module_name).ko构建链的一部分。每个源文件%.c都编译为%.o。如果存在与模块具有相同基本名称的源文件,则相同的文件名有两个目的并且随之而来。在存在单个源文件的特殊情况下,$(module_name).o应该与$(source_file).o完全相同,因此构建链正确。

如果模块有多个源文件,则模块名称必须与任何源文件的名称不同。

我将foo.c重命名为foo_main.c,一切顺利。