主内核 "make" 命令是否也在内部制作模块?

Does the main kernel "make" command also make modules internally?

我正在学习如何编写内核驱动程序,这是我第一次尝试构建内核驱动程序。我为我的模块文件创建了一个文件夹 drivers/naveen/ - hello.cKconfigMakefile。这些是这些文件的内容:

Kconfig

config HELLO_WORLD
        tristate "Hello World support"
        default m
        ---help---
          This option enables printing hello world

生成文件

obj-$(CONFIG_HELLO_WORLD) += hello.o

hello.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

static int __init hello_init(void)
{
    printk(KERN_ERR "This is NAVEEN module");
    return 0;
}

static int __exit hello_exit(void)
{
    printk(KERN_ERR "NAVEEN exiting module");
    return 0;
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("Naveen");
MODULE_LICENSE("GPL");

此外,我在 drivers/Makefile 中添加了以下行:

obj-$(CONFIG_HELLO_WORLD)       += naveen/

drivers/Kconfig 中的以下行:

source "drivers/naveen/Kconfig"

我生成的 .config 包含 CONFIG_HELLO_WORLD=m.

我做了 make ARCH=x86_64 -j16,我可以看到生成了 hello.ko。为什么?我期望只有在我完成 make modules 之后才会生成它,因为它的集合与 .config 中的 m 一样模块化,而不是仅使用 make 进行编译。有人可以向我解释这种行为或我做错了什么吗?

这是否意味着 makemake modules。我可以从 make help 看到 make 实际上意味着 make all 因此它应该在内部也做 make modules ,所以应该没有必要做 make modules一旦制作成功。

你没有做错任何事。 modules 目标自内核版本 2.6.0 以来一直是 all 目标的依赖项(我认为实际上是从内核版本 2.5.60 开始)。

添加模块的方式是将其添加到内核源代码树中。也可以在内核源代码树之外构建自定义模块——所谓的 "out-of-tree" 内核模块。通常,那些不需要 Kconfig 文件,obj-$(CONFIG_HELLO_WORLD) 将在 Makefile 中替换为 obj-m

这是 "out-of-tree" 版本的 "hello" 模块的 Makefile:

ifneq ($(KERNELRELEASE),)
# Kbuild part of Makefile

obj-m += hello.o

else
# Normal part of Makefile
#

# Kernel build directory specified by KDIR variable
# Default to running kernel's build directory if KDIR not set externally
KDIR ?= "/lib/modules/`uname -r`/build"

all:
    $(MAKE) -C "$(KDIR)" M=`pwd` modules

clean:
    $(MAKE) -C "$(KDIR)" M=`pwd` clean

endif

此 Makefile 使用了一个通用技巧,因此可以将同一个 Makefile 作为 "normal" Makefile 和 "kbuild" Makefile 调用。 elseendif 行之间的 "normal" 部分在内核的 Makefile 上调用 $(MAKE)(其位置由 KDIR 变量指定),告诉它在当前目录中构建 modules 目标(由 M=`pwd` 指定)。 "kbuild" 部分位于 ifneq($(KERNELRELEASE),)else 行之间,是构建内核部分的正常 "kbuild" 格式。

该技巧取决于 KERNELRELEASE 变量最初未设置或为空。它将被内核的 Makefile 规则设置为一个非空值。

Linux 内核由两部分组成——核心内核和模块。当我们简单地做 make 时,它的意思是 make all,也就是 make vmlinux && make modules。因此,如果我们已经完成了 make,我们就不需要再做 make modules,我们可以简单地 运行 命令 make modules_install 而无需执行 make modules.