Linux内核中Kconfig和Makefile文件分析
主要关注内核安全模块:/usr/src/linux-xx/security/xxx
这些源码树目录下一般都会有两个文件:Kconfig和Makefile,
1 KConfig
其中分布在各目录下的Kconfig构成了一个分布式的内核配置数据库,每个Kconfig分别描述了所属目录源文件相关的内核配置菜单
也就是说Kconfig对应内核的配置文件,是配置信息的宏定义。
我们以apparmor为例,截取一部分apparmor对应文件夹下的Kconfig文件
config SECURITY_APPARMOR bool "AppArmor support" depends on SECURITY && NET select AUDIT select SECURITY_PATH select SECURITYFS select SECURITY_NETWORK default n help This enables the AppArmor security module. Required userspace tools (if they are not included in your distribution) and further information may be found at http://apparmor.wiki.kernel.org If you are unsure how to answer this question, answer N. config SECURITY_APPARMOR_BOOTPARAM_VALUE int "AppArmor boot parameter default value" depends on SECURITY_APPARMOR range 0 1 default 1 help This option sets the default value for the kernel parameter 'apparmor', which allows AppArmor to be enabled or disabled at boot. If this option is set to 0 (zero), the AppArmor kernel parameter will default to 0, disabling AppArmor at boot. If this option is set to 1 (one), the AppArmor kernel parameter will default to 1, enabling AppArmor at boot. If you are unsure how to answer this question, answer 1. config SECURITY_APPARMOR_HASH bool "Enable introspection of sha1 hashes for loaded profiles" depends on SECURITY_APPARMOR select CRYPTO select CRYPTO_SHA1 default y help This option selects whether introspection of loaded policy is available to userspace via the apparmor filesystem.
那么我们使用make menuconfig编译内核,生成内核菜单,对应与apparmor这一块的内容就是:
可以看出对应关系,depends on代表这个config是在哪一级,bool后面接的是菜单对应的名称。
正式一点的说法呢,bool对应的是该菜单项的类型定义,每个config菜单项都必须有类型定义,bool类型只能选中y/不选中n;除此类型之外,还有tristate内建/模块/移除三态、string字符串、hex十六进制、integer整型。
depends on对应的是该菜单项以来于哪一个菜单项定义,这也就解释了为什么不是KConfig文件里的每一项都会显示,因为依赖于另一项,只有在被依赖的另一项为true时,该项才会显示/才能被选。
即A depends on B:只有B被选中时,才能选A
select表示反向依赖,
即A select B:只要选中A,就会选中B
range表示可选择的范围,比如上方SECURITY_APPARMOR_BOOTPARAM_VALUE就规定了0-1,因为是int型,所以就是选择0/1
default表示默认值
那么每个配置目录前面的[ ]/[*]/[M]是啥呢?这些是读取内核根目录下.config文件生成的配置项,其中[ ]不编译/[*]编译进内核/[M]编译为模块
2 Makefile
LInux内核中每个子目录下的Makefile文件,被称为Kbuild-makefile,它指定当前目录下的文件,哪些被编译进当前目录的built-in.o、那些被编译成模块、那些不编译。定义编译规则
我们还是以security/apparmor作为分析,截取对应子目录下的Makefile文件中的开头部分
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ resource.o secid.o file.o policy_ns.o label.o mount.o net.o \ af_unix.o apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o clean-files := capability_names.h rlim_names.h net_names.h
如$(CONFIG_SECURITY_APPARMOR) 是一个整体,表示引用CONFIG_SECURITY_APPARMOR变量,我们发现这个变量在KConfig文件中有对应。
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o //把apparmor添加进内核配置系统
而后面的apparmor-y := apparmorfs .o audit.o ... 则表示会创建一个基于apparmorfs .o&audit.o&... 的库文件,即需要编译链接后面一系列.o文件。
除了y(编译进内核)或m(编译进模块)以外的obj-x形式的目标都不会被编译
:= 覆盖之前的值,即变量的值取决于它的makefile的位置,不是整个makefile展开后的值。
+=添加等号后的值
3 使用make menuconfig的流程
首先确定架构arch,然后读取arch目录的Kconfig中的配置宏定义,生成编译条目,然后读取Linux内核根目录下的.config选项, 将.config中的配置信息显示在图形界面上[*] [M] or []。在图形界面中更改配置选项会自动保存到.config文件中。编译过程根据.config随后生成auto.conf文件,它决定了makefile中各个文件的编译类型,静态编译进内核、编译成模块、不编译;同时生成autoconf.h,它以C语言宏定义的形式表达了 各个文件是否被编译,源码中会判断某文件是否被编译进行不同的处理。 (https://blog.csdn.net/lizuobin2/article/details/51429937)