具有多个源文件的内核模块中缺少组件
我有一个带有单个 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 的调用
函数。 (好吧,在现实生活中,我在标头中声明了 aux 函数,我的代码不仅仅打印一条消息,但我已将问题缩小到这个小示例。)并且我添加了在 makefile 中声明模块组件的行,位于 foo.c
中的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。
I had a little module with a single C source file foo.c
, and all was well.
#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");
The Makefile
was simple:
obj-m += foo.o
Now that the source has grown, I want to add a second source file bar.c
:
#include <linux/init.h>
#include <linux/module.h>
int aux(int x) {
return x + 1;
}
I've added a call to the aux
function in foo.c
. (Well, in real life I declare the aux
function in a header, and my code does more than print a message, but I've shrunk my problem to this small example.) And I've added a line to declare the components of the module in the makefile, following Documentation/kbuild/makefiles.txt
.
foo-objs += bar.o
obj-m += foo.o
But now, when I build the module, it seems that foo.o
is not linked (modinfo
reports no module license and author, nm foo.ko
doesn't find the symbols defined in foo.c
, foo_init
is evidently not run when I load the module). Putting foo-objs := foo.o bar.o
in the makefile doesn't help.
Why does adding a second source file displace the first source file, and how do I get foo
back?
In case this matters: the kernel version is 2.6.35, the architecture is arm, and the module is in-tree.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为了编译你的东西,我建议将
foo.c
重命名为foo-base.c
(想法是不要有.c< /code> 文件与模块同名。
foo-objs
将从您指定的其他对象构建foo.o
,但不会来自foo.c
)。然后你可以这样做:(
foo-y := ...
也可以,但是我看过的 Makefiles 使用-objs
版本。)它应该可以工作:
[也就是说,在您为示例中的
printk
提供了足够的参数之后:-)]注意:在重建模块之前,不要忘记清理所有生成的文件那个改变。
To get your thing to compile, I'd suggest renaming
foo.c
to e.g.foo-base.c
(the idea being not to have a.c
file with the same name as the module. Thefoo-objs
will buildfoo.o
from the other objects you specify but not fromfoo.c
).Then you can do:
(
foo-y := ...
works too, but the Makefiles I've looked at use the-objs
version.)And it should work:
[that is, after you've given enough arguments to
printk
in your sample :-)]Note: don't forget to clean up all the generated files before rebuilding your module after that change.
缩小到一个小例子就可以解决这个问题的 90%。它让我看到,在 makefile 中使用
foo-objs := foo.o bar.o
时,make
会抱怨:使用
foo 更难检测到该问题-objs += bar.o
,但它隐藏在make V=1
的输出中:幕后发生的事情是
$(module_name).o
code> 是构建链的一部分$(module_name).ko
。每个源文件%.c
都会编译为%.o
。如果存在与模块具有相同基本名称的源文件,则相同的文件名有两个用途,并且会发生严重破坏。在只有一个源文件的特殊情况下,$(module_name).o
应该与$(source_file).o
相同,因此构建链如下出来吧。如果一个模块有多个源文件,则模块名称必须与任何源文件的名称不同。
我将 foo.c 重命名为 foo_main.c ,一切都很好。
Shrinking down to a small example was 90% of solving this. It let me see that, with
foo-objs := foo.o bar.o
in the makefile,make
complains:The trouble is harder to detect with
foo-objs += bar.o
, but it's hidden in the output frommake V=1
:What's going on under the hood is that
$(module_name).o
is part of the build chain for$(module_name).ko
. Each source file%.c
is compiled to%.o
. If there's a source file with the same base name as the module, the same file name has two purposes and havoc ensues. In the special case where there's a single source file,$(module_name).o
is supposed to be identical to$(source_file).o
anyway, so the build chain comes out right.If a module has more than one source file, the module name must be distinct from the name of any source file.
I renamed
foo.c
tofoo_main.c
and all is well.