2011-09-20 69 views
1

我有一个带有单个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; 
} 

我已经加入到呼叫在foo.c中的aux函数。 (好吧,在现实生活中,我在头文件中声明了aux函数,而我的代码不仅仅是打印一条消息,而且我将这个问题缩小到这个小例子。)并且我添加了一行来声明组件makefile中的模块,位于Documentation/kbuild/makefiles.txt之后。

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

但是现在,当我构建模块,似乎foo.o不挂(modinfo没有报告任何模块的许可和作者,nm foo.ko没有找到foo.c定义的符号,foo_init明显未当我运行加载模块)。将foo-objs := foo.o bar.o放在makefile中不起作用。

为什么添加第二个源文件会取代第一个源文件,并且如何返回foo

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

回答

1

为了让你的东西编译,我建议将foo.c重命名为例如foo-base.c(的想法是不是有一个.c文件具有相同的名称作为模块,foo-objs将建立从您指定的其他对象foo.ofoo.c)。

然后,你可以这样做:

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

foo-y := ...工作过,但Makefile文件我看了使用-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的足够参数之后:-)]

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

+0

谢谢,我最终发现它(我写了一个答案解释了如何 - 写一个小例子来问这个问题是解决问题的90%)。这个问题确实有一个与模块名称相同的源文件。 – Gilles

0

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

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,一切都很好。