探索Linux内核:Kconfig的秘密

深入了解Linux配置/构建系统是如何工作的。

嵌入式进阶教程分门别类整理好了,看的时候十分方便,由于内容较多,这里就截取一部分图吧。

需要的朋友私信【内核】即可领取。


为了探索Linux内核是如何编译的,本文将深入研究Kconfig/kBuild内部进程,解释.config文件和vmlinux/bzImage文件是如何生成的,并介绍一个用于依赖性跟踪的智能技巧。

Kconfig

构建内核的第一步就是配置。Kconfig帮助使Linux内核高度模块化和可定制。Kconfig为用户提供了许多配置目标:

config

使用面向行的程序更新当前配置

nconfig

使用基于ncurses菜单的程序更新当前配置

menuconfig

使用基于菜单的程序更新当前配置

xconfig

利用基于qt的前端更新当前配置

gconfig

利用基于GTK+的前端更新当前配置

oldconfig

使用提供的.config作为基础更新当前配置

localmodconfig

更新未加载的当前配置禁用模块

localyesconfig

更新当前配置,将本地MODS转换为核心

defconfig

从Arch提供的Defconfig中获得默认配置的新配置

Savedefconfig

将当前配置保存为./defconfig(最小配置)

allnoconfig

使用“no”回答所有选项的新配置

allyesconfig

新配置,在该配置中,所有选项都以“是”接受

allmodconfig

在可能的情况下选择新的配置模块

alldefconfig

将所有符号设置为默认值的新配置

randconfig

具有对所有选项的随机答案的新配置

listnewconfig

列出新选项

olddefconfig

与oldconfig相同,但在不提示的情况下将新符号设置为默认值

kvmconfig

为kvm客户端内核支持启用其他选项

xenconfig

启用Xom0和来宾内核支持的其他选项

tinyconfig

配置尽可能小的内核

我认为menuconfig是这些目标中最受欢迎的。目标由不同的主机程序进行处理,这些程序由内核提供,并在内核构建过程中生成。一些目标有一个GUI(为了用户的方便),而大多数没有。与kconfig相关的工具和源代码主要位于scripts/kconfig/在内核源代码中。我们可以从scripts/kconfig/makefile,有几个主机程序,包括CONF,mconf,和nconf。除了CONF,它们每个都负责基于GUI的配置目标之一,因此,CONF和他们中的大多数人打交道。

从逻辑上讲,Kconfig的基础结构有两个部分:一个实现了新语言要定义配置项(请参阅内核源代码下的Kconfig文件),而其他配置项则解析Kconfig语言并处理配置操作。

大多数配置目标的内部流程大致相同(如下所示):

注意,所有配置项都有一个默认值。

第一步读取源根下的Kconfig文件以构造初始配置数据库;然后根据此优先级读取现有配置文件来更新初始数据库:

.config

/lib/Module/$(shell,uname-r)/.config

/etc/kernel-config

/boot/config-$(shell,uname-r)

ARCH_DEFCONFIG

ARCH/$(ARCH)/Defconfig

如果您正在进行基于GUI的配置,则通过menuconfig或基于命令行的配置oldconfig,数据库将根据您的自定义进行更新。最后,将配置数据库转储到.config文件中。

但是.config文件不是内核构建的最终素材;这就是为什么syncconfig目标存在。syncconfig以前是一个名为silentoldconfig,但是它不像旧名字说的那样,所以它被重命名了。此外,由于它是内部使用(而不是为用户),它被从列表中删除。

下面是一个例子syncconfig作用:

syncconfig接受.config作为输入并输出许多其他文件,这些文件分为三类:

用于生成文件文本处理。例如,您可能在组件的makefile中看到这样的语句:

obj-$(CONFIG_GENERIC_CALIBRATE_DELAY)+=

在C语言源文件中使用。

空头文件include/config/用于在kbuild期间进行配置依赖项跟踪,下面将对此进行解释。

配置之后,我们将知道哪些文件和代码段没有编译。

KBuild

组件式建筑,称为递归制作,是GNU的一种常见方式。制作,是管理一个大型项目。KBuild是递归make的一个很好的例子。通过将源文件划分为不同的模块/组件,每个组件都由自己的Makefile管理。当您开始构建时,顶级Makefile按正确的顺序调用每个组件的makefile,构建组件,并将它们收集到最终的执行程序中。

KBuild指的是不同类型的makefile:

.config是内核配置文件。

scripts/Makefile*描述所有kbuildmakefile的通用规则。

最后,大约有500个Kbuildmakefiles.

例如,让我们看看在x86-64上如何生成vmlinux:

(插图是根据理查德·Y·史蒂文()的博客。经提交人许可后予以更新和使用。

所有.o进入vmlinux的文件首先进入它们自己的,这是通过变量表示的。KBUILD_VMLINUX_INIT,KBUILD_VMLINUX_Main,KBUILD_VMLINUX_LIBS,然后收集到vmlinux文件中。

看看如何在Linux内核中实现递归make,并借助简化的Makefile代码:

Variableassignmentsvmlinux-deps:=$(KBUILD_LDS)$(KBUILD_VMLINUX_INIT)$(KBUILD_VMLINUX_MAIN)$(KBUILD_VMLINUX_LIBS)exportKBUILD_VMLINUX_INIT:=$(head-y)$(init-y)exportKBUILD_VMLINUX_MAIN:=$(core-y)$(libs-y2)$(drivers-y)$(net-y)$(virt-y)exportKBUILD_VMLINUX_LIBS:=$(libs-y1)exportKBUILD_LDS:=arch/$(SRCARCH)/kernel/:=init/drivers-y:=drivers/sound/firmware/net-y:=net/libs-y:=lib/core-y:=usr/virt-y:=virt/,"4.6PhonyTargets"of`infomake`$(sort$(vmlinux-deps)):$(vmlinux-dirs);Theentryofrecursivemake$(vmlinux-dirs):$(Q)$(MAKE)$(build)=$@need-builtin=1

递归的配方扩展,例如:

make-fscripts/=initneed-builtin=1

这意味着make将进入scripts/继续建造每一个。在.的帮助下scripts/,vmlinux文件最终位于源根下。

理解vmlinux与bzImage

许多Linux内核开发人员可能不清楚vmlinux和bzImage之间的关系。例如,以下是它们在x86-64中的关系:

源根vmlinux被剥离、压缩、放入,然后将其他对等对象链接到arch/x86/boot/compressed/vmlinux。同时,下面生成一个名为的文件arch/x86/boot。可能有一个包含重定位信息的可选的第三个文件,具体取决于config_x86_RELOCS.

一个名为build由内核提供,将这两个(或三个)部分构建到最终的bzImage文件中。

依赖跟踪

KBuild跟踪三种依赖关系:

所有的前提文件(*.c和*.h)

CONFIG_在所有先决条件文件中使用的选项

用于编译目标的命令行依赖关系。

第一个很容易理解,但是第二个和第三个呢?内核开发人员经常看到这样的代码片段:

if

什么时候CONFIG_SMP更改后,这段代码应该重新编译。编译源文件的命令行也很重要,因为不同的命令行可能导致不同的对象文件。

当.C文件通过include源文件中的行。对于GNU编译器集合(GCC),只需添加一个命令行参数:-MDdepfile

Thecommandlineusedtocompilethetargetcmd_init/init_:=gcc-Wp,-MD,init/.init_#Thedepencyfilesdeps_init/init_:=\$(wildcardinclude/config/posix/)\$(wildcardinclude/config/arch/task/struct/on/)\$(wildcardinclude/config/thread/info/in/)\include/uapi/linux/\arch/x86/include/uapi/asm/\include/uapi/asm-generic/\

在递归生成过程中将包含一个.cmd文件,提供所有依赖项信息,并帮助决定是否重新构建目标。

这背后的秘密是,Fixdep将解析depfile(.d文件),然后解析其中的所有依赖文件,搜索所有config_string的文本,将它们转换为相应的空头文件,并将它们添加到目标的先决条件中。每次配置更改时,相应的空头文件也将被更新,因此kbuild可以检测到该更改并重新构建依赖于它的目标。因为还记录了命令行,所以很容易比较最后的编译参数和当前的编译参数。

展望未来

Kconfig/kbuild很长一段时间没有变化,直到新的维护者山田正一郎(MasahiroYamada)在2017年初加入,现在KBuild又在积极发展。如果你很快看到了与本文不同的东西,不要感到惊讶。

原文地址:,侵删

版权声明:本站所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,不声明或保证其内容的正确性,如发现本站有涉嫌抄袭侵权/违法违规的内容。请举报,一经查实,本站将立刻删除。

相关推荐