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

发布于 2024-12-05 08:25:22 字数 1324 浏览 3 评论 0原文

我有一个带有单个 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 函数,我的代码不仅仅打印一条消息,但我已将问题缩小到这个小示例。)并且我添加了在 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。

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2024-12-12 08:25:23

为了编译你的东西,我建议将 foo.c 重命名为 foo-base.c (想法是不要有 .c< /code> 文件与模块同名。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 提供了足够的参数之后:-)]

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

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. The foo-objs will build foo.o from the other objects you specify but not from foo.c).

Then you can do:

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

(foo-y := ... works too, but the Makefiles I've looked at use the -objs version.)
And it should work:

$ 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 

[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.

Hello爱情风 2024-12-12 08:25:23

缩小到一个小例子就可以解决这个问题的 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 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:

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

The trouble is harder to detect with foo-objs += bar.o, but it's hidden in the output from make V=1:

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

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 to foo_main.c and all is well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文