ILD

kbuild学习1
作者:Herbert Yuan 邮箱:yuanjp@hust.edu.cn
发布时间:2019-5-16 站点:Inside Linux Development

今天开始踏入内核学习的门。


前言

The Kernel Build System (kbuild) 包含4个主要部分:


Config symbols

条件编译选项,用来决定哪些目标编译进内核或内核模块。


Kconfig files

定义每个config symbols和它的属性,


.config files

存储每一个符号的定义。可以手动编辑该文件。也可以用其它工具生成,如menuconfig。


Makefiles

普通的GNU Makefile文件,根据编译符号实现内核编译。


1 Compilation Options: Configuration Symbols

配置符号用来决定哪些features将被包含到最后的内核镜像。有两种符号:布尔和三太。Boolean symbols有两种值true或者false。Tristate symbols有3种值: yes no 或者module。

不是内核的一切东西都可以编译为模块,例如SMP或者kernel preemption,因此这种情况下,使用布尔配置符号。大多数功能可以编译为模块,也可以在编译时添加到内核,因此有3种选择,built-in(y), module(m), 或者不编译。

除了上面两种,还有其它类型的配置符号,例如字符串和16进制,但是因为他们不是用来条件编译的。


2 Defining Configuration Symbols: Kconfig Files

配置符号定义在被叫做Kconfig的文件中,每个Kconfig文件可以描述任意数量的符号,也可以include(source)其它Kconfig文件。创建内核编译选项的配置菜单的编译目标,例如make menuconfig,读取这些文件,创建树型结构。内核中的每一个目录有一个kconfig文件(haha,not true),它还包含子目录中的kconfig文件。在内核源码的顶层有一个kconfig文件,这个文件是选项树的根。menuconfig(scripts/kconfig/mconf), gconfig(scripts/kconfig/gconf)和其它的编译目标调用程序从根kconfig开始,迭代读取所有子目录的kconfig来创建菜单。要访问哪个子目录,也是在kconfig文件中定义的,同样依赖用户选择的配置符号。


3 Storing Symbols Values: .config File

所有的配置符号值存储在一个特殊的文件,叫做.config。每个你想改变一个内核编译配置,你执行一个make目标,例如menuconfig或者xconfig,它们读取kconfig来构建菜单,并使用.config文件来更新配置符号值,当你改变一些选项后,这个些工具更新.config,如果.config之前不存在,也会产生一个。


4 Compiling the Kernel: Makefiles

kbuild系统的最后一个部分是Makefiles,他们用来编译内核镜像和模块,像kconfig文件一样,每个子目录有一个Makefile文件,只编译它的目录下的文件。整个编译是迭代的,top Makefile descends进它的子目录,执行每个子目录的Makefile来产生目标文件。这些目标文件用来产生模块和内核镜像。


5 Example

当执行一个编译目标来编译内核或者一个模块时,首先执行一个二进制来读取所有的kconfig文件和.config

1
$ scripts/kconfig/conf Kconfig

这个二进制更新或者创建一个C头文件,包含你选择的所有的配置符号,这个文件是include/generated/autoconf.h,每一个gcc编译指令都包含它,所以这些符号可以在内核的任何源码中使用。


如果布尔值CONFIG_COIN_STAT为真,3态值CONFIG_COIN为y,那么产生:

1
2
3
4
5
6
7
#define __enabled_CONFIG_COIN_STAT 1
#define __enabled_CONFIG_COIN_STAT_MODULE 0
#define CONFIG_COIN_STAT 1
 
#define __enabled_CONFIG_COIN 1
#define __enabled_CONFIG_COIN_MODULE 0
#define CONFIG_COIN 1


如果布尔值为假,3态值为no,则产生:

1
2
3
4
5
#define __enabled_CONFIG_COIN_STAT 0
#define __enabled_CONFIG_COIN_STAT_MODULE 0
 
#define __enabled_CONFIG_COIN 0
#define __enabled_CONFIG_COIN_MODULE 0


如果3态值为module,则产生:

1
2
3
#define __enabled_CONFIG_COIN 0
#define __enabled_CONFIG_COIN_MODULE 1
#define CONFIG_COIN_MODULE 1


相关的宏有:

1
2
3
4
5
6
#define IS_ENABLED(option) \
        (__enabled_ ## option || __enabled_ ## option ## _MODULE)
 
#define IS_BUILTIN(option) __enabled_ ## option
 
#define IS_MODULE(option) __enabled_ ## option ## _MODULE


内核编译系统有两个主要任务,创建内核镜像和内核模块,为此,它维护两个目标列表obj-y和obj-m。前者用来编译内核镜像,后来用来编译内核模块。


为了编译源码,在Makefile中,只需要:

1
obj-$(CONFIG_COIN) += coin.o


这告诉内核从源码coin.c创建目标文件,将它添加到上述列中。


参考

http://www.linuxjournal.com/content/kbuild-linux-kernel-build-system


Copyright © insidelinuxdev.net 2017-2021. Some Rights Reserved.