探索Linux内核:Kconfig的秘密-创新互联

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

专注于为中小企业提供成都做网站、网站建设服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业玉环免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上千企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

自从Linux内核代码迁移到Git之后,Linux内核配置/构建系统(也称为Kconfig/kBuild)已经存在了很长时间。然而,作为支持基础设施,它很少受到关注;即使在日常工作中使用它的内核开发人员也从未真正考虑过它。

为了探索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 启用Xen dom0和来宾内核支持的其他选项
tinyconfig 配置尽可能小的内核

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

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

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

探索Linux内核: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作用:

探索Linux内核:Kconfig的秘密

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

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

obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o

autoconf.h在C语言源文件中使用。

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

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

KBuild

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

KBuild指的是不同类型的makefile:

  • Makefile位于源根中的顶部makefile。
  • .config是内核配置文件。
  • ARCH/$(ARCH)/Makefile是拱形Makefile,这是对顶部makefile的补充。
  • scripts/Makefile*描述所有kbuild makefile的通用规则。
  • 最后,大约有500个Kbuildmakefiles.

顶部的makefile包含archmakefile,读取.config文件,进入子目录,调用制作,使中定义的例程的帮助下实现每个组件的makefile。scripts/Makefile*,构建每个中间对象,并将所有中间对象链接到vmlinux。核心文件Documentation/kbuild/makefiles.txt描述这些制作文件的所有方面。

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

探索Linux内核:Kconfig的秘密

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

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

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

# In top Makefile
vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps)
        +$(call if_changed,link-vmlinux)
# Variable assignments
vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) $(KBUILD_VMLINUX_LIBS)
export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y)
export KBUILD_VMLINUX_LIBS := $(libs-y1)
export KBUILD_LDS     := arch/$(SRCARCH)/kernel/vmlinux.lds
init-y     := init/
drivers-y    := drivers/ sound/ firmware/
net-y      := net/
libs-y     := lib/
core-y     := usr/
virt-y     := virt/
# Transform to corresponding built-in.a
init-y     := $(patsubst %/, %/built-in.a, $(init-y))
core-y     := $(patsubst %/, %/built-in.a, $(core-y))
drivers-y    := $(patsubst %/, %/built-in.a, $(drivers-y))
net-y      := $(patsubst %/, %/built-in.a, $(net-y))
libs-y1     := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2     := $(patsubst %/, %/built-in.a, $(filter-out %.a, $(libs-y)))
virt-y     := $(patsubst %/, %/built-in.a, $(virt-y))
# Setup the dependency. vmlinux-deps are all intermediate objects, vmlinux-dirs
# are phony targets, so every time comes to this rule, the recipe of vmlinux-dirs
# will be executed. Refer "4.6 Phony Targets" of `info make`
$(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
# Variable vmlinux-dirs is the directory part of each built-in.a
vmlinux-dirs  := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
           $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
           $(net-y) $(net-m) $(libs-y) $(libs-m) $(virt-y)))
# The entry of recursive make
$(vmlinux-dirs):
        $(Q)$(MAKE) $(build)=$@ need-builtin=1

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


文章名称:探索Linux内核:Kconfig的秘密-创新互联
当前URL:http://azwzsj.com/article/shdsj.html