如何在Linux内核模块中包含本地头文件

如何在Linux内核模块中包含本地头文件

假设我有一个包含源文件的模块,mymod如下所示:

src/mod/mymod.c
src/inc/mymod.h

我尝试包含 mymod.h 如下

#include <mymod.h>

我的 makefile 包含EXTRA_CFLAGS= -I$(shell pwd)/../inc/但当内核制作时,我收到一条错误消息:

找不到 mymod.h

原因似乎是当创建内核模块时,此命令从 makefile 运行:(使用makeV1):

make -C <path/to/linux/src> M=<path/to/mymod> modules

在其他作品中,我的内容$(shell pwd)扩展到了<path/to/linux>.这不是我想要的。如何指定-I指向源树src/inc的参数mymod

答案1

Linux 内核 makefile 使用 Kbuild 框架。尽管这些是由 GNU make 解释的,但 Kbuild 包含大量具有特殊使用约定的宏,因此典型的 makefile 指南不适用。 Kbuild 的好处是考虑到任务的复杂性,您只需要很少的样板文件。

Kbuild 记录在内核源代码中,位于Documentation/kbuild。作为模块编写者,您应该特别阅读modules.txt(至少浏览一下其他的)。

您现在所做的不起作用,因为使用变量$(shell pwd)时会扩展。EXTRA_CFLAGS由于 makefile 从内核源代码树运行,而不是从模块目录运行(这是 Kbuild 的许多非显而易见的方面之一),因此它选择了错误的目录。

在树外模块中指定包含目录的官方习惯用法位于 的 §5.3 中modules.txt。该src变量设置为模块的顶级目录。所以:

EXTRA_CFLAGS := -I$(src)/src/inc

Kbuild请注意,此声明应位于模块树根部调用的文件中。 (您可能希望将该src目录视为模块树的根;如果是这样,请将其放在Kbuild那里并用 替换上面的值-I$(src)/inc)。也可以将它们放在 a 中Makefile,但请注意,此定义(只要仅在构建内核模块时适用的其他任何内容)应该位于条件指令中ifeq ($(KERNELRELEASE),)。请参阅第 4.1 节modules.txt

如果您还没有Kbuild文件并且想要切换到拥有文件,请阅读 的第 §4.1 节modules.txt。有一个单独的Kbuild文件会稍微清晰一些。除了调用规则之外,不要将任何适用于内核的内容放入主 makefile 中make -C $(KERNELDIR) M=$(pwd)。在 中Kbuild,您至少需要的是您正在构建的模块列表(通常只是一个)和要包含在模块中的文件列表,以及依赖项声明:

EXTRA_CFLAGS := -I$(src)/inc
obj-m := mymod.o
mymod-y := $(src)/mod/mymod.o
$(src)/mod/mymod.o: $(src)/inc/mymod.h

答案2

#include传统上,获取具有相对于当前源代码目录的路径的文件的方法是使用引号而不是尖括号:

#include <stdio.h>
#include "mygreatfunctions.h"

在这种情况下,第一个#include将引用编译器的包含搜索路径(在 gcc 的情况下,由-I命令行开关控制),而第二个将在包含带有#include.

这样的路径也可以是相对的。所以在 src/mod/mymod.c 中,你可以说:

#include "../inc/mymod.h"

它应该“正常工作”。

我不知道这在 Linux 内核树中是否是常见做法,但肯定比乱搞包含路径要好,后者可能会产生许多意想不到的副作用。

相关内容