系列 | 内容 |
---|---|
深入理解linux内核 | 内核编译机制分析 |
环境:
平台 | 内核版本 | 安卓版本 |
---|---|---|
RK3399 | Linux4.4 | Android7.1 |
Linux
内核从源码到安装使用大致可分三个阶段,配置,编译,安装。配置的过程主要由 Kconfig
提供的图形界面完成,也有部分工作由 Kbuild
完成。编译的实现机制主要是Kbuild
系统,由make
命令完成内核编译。内核的安装也是由Kbuild
提供的安装脚本再由 make
命令执行安装。
文章目录
1、Kconfig
Kconfig
文件用于 Linux
内核的配置。各目录中的 Kconfig
一起构成了一个分布式的内核配置数据库,每个 Kconfig
分别描述了所属目录源文档相关的内核配置菜单,就是我们使用命令 make %config
(如 menuconfig
)后产生的配置菜单,此菜单包含多层,每个层次都是由各个目录中的 Kconfig
产生的。然后根据用户的需求来选择如何编译内核,再将配置结果存到.config
中,然后执行 Makefile
时就会根据.config
的结果来实现内核的编译。
1.1、Kconfig语法分析
配置文件描述了菜单选项,每行都是以一关键字开头(除了帮助信息)。以下列出主要关键字:
关键字 | 内容 |
---|---|
config |
config 是构成 Kconfig 的最基本单元,其中定义了配置项的详细信息。 |
menu/endmenu |
menu 的作用,可以理解成一个目录,可以把一部分相关配置项包含到一个menu 中,这样有利于配置的分类显示,menu 中也可以嵌套包含 menu 。 |
menuconfig |
menuconfig 有点类似 menu ,但区别就在于 menu 后面多了一个 config ,这个menu 是可以配置的,前面比 menu 类型多了一个方框,通过空格可以修改这个配置项的选中状态。若选中进入该菜单项时和普通的 menu 是一样的。 |
if/endif |
if/endif 搭配使用,说明配置项是位于 if 和 endif 中。if/endif 中的部分就是MODULES 子目录显示的内容。如果选中了 MODULE ,那么 if 和 endif 中的内容可以显示。如果没有定义,就只能进入一个空目录。 |
choice/endchoice |
choice 的作用,定义了一组选择项,从中选择一个。该配置项的类型只能是bool 或者 tristate 。 |
comment |
定义了在配置过程中显示给用户的注释,其中唯一可选的属性是依赖关系depends on |
source |
source 用来读取指定的配置文件,通过 source 就可以将各目录下的 Kconfig 文件层层嵌套进来,类似 C 语言中的 include 。 |
2、Kbuild
Kbuild
,即 Kernel build
,用于编译 Linux
内核文件。Kbuild
对 makefile
进行了功能上的扩充,使其在编译内核文件时更加高效,简洁。
从 Linux
内核 2.6
开始,Linux
内核的编译采用 Kbuild
系统,这同过去的编译系统有很大的不同,尤其对于Linux
内核模块的编译。在新的系统下,Linux
编译系统会两次扫描 Linux
的 Makefile
:首先编译系统会读取 Linux
内核顶层的 Makefile
,然后根据读到的内容第二次读取Kbuild
的 Makefile
来编译 Linux
内核。
内核 Makefile
一共包括五部分:
文件 | 内容 |
---|---|
顶层 Makefile |
顶层 Makefile 文件定义两个主要的目标:vmlinux (内核映像)和所有的模块。顶层 Makefile 文件根据内核配置,通过递归编译内核代码树子目录建立这两个文件。 |
.config |
配置完成后生成.config 文件,Kbuild 中的 Makefile 会读取该文件的配置,比如各目录中的 Makefile 会查看某一个项配置的是 y 还是 n 。 |
arch/$(ARCH)/Makefile |
顶层 Makefile 文件引用了一个名为 arch/$(ARCH)/Makefile 的文件,这个文件提供了与平台相关的一些信息。 |
scripts/Makefile.* |
scripts/Makefile.* 包含了所有的定义和规则,与Makefile 文件一起编译出内核映像。 |
各目录中的Makefile 文件 |
每一个子目录有一个 Makefile 文件,子目录 Makefile 文件根据上级目录Makefile 文件命令启动编译。这些 Makefile 使用.config 文件配置数据构建各种文件列表,并使用这些文件列表编译内嵌或模块目标文件。 |
3、Makefile
3.1、顶层Makefile分析
顶层 Makefile
在编译时是入口点,从整体上组织所有的 Makefile
文件,并定
义终极目标,在这里还定义了与平台无关的很多核心变量与一些很重要的 make
目标。顶层 Makefile
位于内核源码的根目录,下面我们分析顶层 Makefile
的主要工作。
顶层 Makefile
定义并向环境中输出了许多变量,为各个子目录下的Makefile
传递一些信息。有些变量,比如 vmlinux-dirs
,不仅在顶层 Makefile
中定义并且赋初值,而且在 arch/*/Makefile
还作了扩充。
变量 | 内容 |
---|---|
内核版本 | 版 本 信 息 定 义 了 当 前 内 核 的 版 本 , VERSION=3 , PATCHLEVEL=5 ,SUBLEVEL=4 ,EXATAVERSION= ,它们共同构成内核的发行版本号为 3.5.4 。 |
CPU 体系结构 | 用 ARCH 定义目标 CPU 的体系结构,比如 ARCH:=arm 等。 |
源码路径 | 很多 scripts/Makefile.* 规则被很多不同目录下的 Makefile 所共享,所以要针对不同的路径操作不同的文件,就需要定义当前的相对路径。 |
递归目录定义 | init-y , core-y , libs-y , drivers-y , net-y 。 |
编译选项 | 如 CPP , CC , AS , LD , AR ,KBUILD_CFLAGS ,LDFLAGS_vmlinux 等编译参数。 |
3.2、平台相关Makefile分析
arch/$(ARCH)/Makefile
定义了所有与平台相关的部分,主要对顶层 Makefile
中定义的一些变量作与平台相关的扩展。 Linux
最大的特点是支持跨平台,这种跨平台,不像是 JAVA
那样运行于一个底层虚拟平台上,而是定义很多与平台相关的 Makefile
负责的。
3.3、各目录下Makefile
内核中的 Makefile
文件都是采用 Kbuild
架构,一般情况下,建议我们采用Makefile
作为管理当前目录代码的 makefile
文件名,但是有时候也可以使用Kbuild
,但当两者同时存在于同一个目录下时,Kbuild
将会被优先使用。 分布在各个子目录下的 Makefile
,它们并不符合 GNU Makefile
的语法,为了区别于通常意义上的 Makefile
,所以被称为 Kbuild Makefile
。