我有一个带有单个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。
答案 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.o
,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
,一切顺利。