模块编译:未找到 asm/linkage.h 文件

19
我正在尝试编译一个“hello world”内核模块的示例,遇到了一些问题。这些问题出现在Ubuntu 11.04、内核3.2.6、gcc 4.5.2和Fedora 16、内核3.2.7、gcc 4.6.7上。
代码:
#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");

static int __init hello_init (void)
{
printk("Hello module init\n");
return 0;
}
static void __exit hello_exit (void)
{
printk("Hello module exit\n");
}
module_init(hello_init);
module_exit(hello_exit);

编译时使用的:

gcc -D__KERNEL__ -I /usr/src/linux/include/ -DMODULE -Wall -O2 -c hello.c -o hello.o

错误信息:

在文件/usr/src/linux/include/linux/kernel.h:13:0中包含, 来自/usr/src/linux/include/linux/cache.h:4, /usr/src/linux/include/linux/time.h:7, /usr/src/linux/include/linux/stat.h:60, /usr/src/linux/include/linux/module.h:10, hello.c:1: /usr/src/linux/include/linux/linkage.h:5:25: 致命错误: asm/linkage.h: 没有那个文件或目录

然后我发现在/usr/src/linux/include/中没有名为'asm'的文件夹,但有'asm-generic'; 所以我创建了一个符号链接'asm'指向'asm-generic',再次编译:

这一次错误变成:

在文件/usr/src/linux/include/linux/preempt.h:9:0中包含, 来自/usr/src/linux/include/linux/spinlock.h:50, /usr/src/linux/include/linux/seqlock.h:29, /usr/src/linux/include/linux/time.h:8, /usr/src/linux/include/linux/stat.h:60, /usr/src/linux/include/linux/module.h:10, hello.c:1: /usr/src/linux/include/linux/thread_info.h:53:29: 致命错误: asm/thread_info.h: 没有那个文件或目录

所以我意识到我错了,但是为什么呢?T_T

5个回答

13
obj-m += hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

这是构建模块的正确方式,请查看kbuild文档

要查看编译器调用之间的差异,您可以

cat /lib/modules/$(shell uname -r)/build/Makefile

分析输出结果


1
这个Makefile如何添加到cmake中?(CMakeFiles.txt) - Emre

4
obj-m += hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

这里的hello.c是你的内核源文件。只需使用make命令来构建你的hello.ko模块。


5
我知道这个命令可以工作,但为什么按照我的方式就不行呢?“gcc -D__KERNEL__ -I /usr/src/linux/include/ -DMODULE -Wall -O2 -c hello.c -o hello.o” - Raiden Awkward

1

asm 应该链接到实际的正在编译的体系结构,而不是 asm-generic
你不能编译一个通用的内核模块,这个内核模块可以在通用的架构上工作。你必须为你将要使用的特定架构编译它。

我不知道为什么没有 asm。它应该在配置过程中被创建。
如果配置不完整,你可能会在后面遇到其他错误。


我已经在三台机器上检查了Ubuntu、Fedora和Gentoo上的内核源代码文件夹(3.2+),它们都不包含'asm'文件夹。因此,我认为这可能不是一个错误。 - Raiden Awkward
2
在Redhat中,我检查了/usr/src/kernels/.../include/asm,它是指向asm-x86_64的链接。 - ugoren

0

asm 包括(例如 linkage.h)是与体系结构相关的。应该在以下目录下设置一组目录:

    /usr/src/kernels/(kernel version goes here)/arch

这提供了针对您要编译代码的特定CPU架构的特定包含文件。

尝试将此添加到您的Makefile中:

    KVERSION :=R(shell uname -r)

并添加内核和架构(在此示例中为x86):

    INCDIRS = -I./include -I/usr/src/kernels/$(KVERSION)/include -I/usr/src/kernels/$(KVERSION)/arch/x86

-1

模块编译:找不到 asm/linkage.h 文件

这意味着在使用 make 的 -I 选项指定的 DIR 中未找到此特定文件。

如果所有标头都存在于 asm-generic 中,我们可以将该 asm-generic 链接到 asm,或者我们可以使用 make 实用程序

在构建内核模块时,首选使用 Make 实用程序。

在工作目录中创建一个 'Makefile'。

obj-m += hello.o
all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

使用 -C 选项将在读取 makefiles 或执行任何其他操作之前更改为指定的 DIR。

因此,为了避免这个错误,请使用 -C 选项和 DIR/lib/modules/$(shell uname -r)/build

通过这样做,您的程序将能够找到所需的文件,您将获得 hello.ko 文件。

您可以将其添加到内核模块中

sudo insmod hello.ko

同样,你可以通过

来移除。
sudo rmmod hello

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接