配置系统的基本结构
Linux内核的配置系统由三个部分组成,分别是:
1、Makefile:分布在 Linux 内核源代码根目录及各层目录中,定义 Linux 内核的编译规则;
2、配置文件(config.in(2.4内核,2.6内核)):给用户提供配置选择的功能;
3、配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释)和配置用户界面(提供基于字符界面、基于 Ncurses 图形界面以及基于 Xwindows 图形界面的用户配置界面,各自对应于 Make config、Make menuconfig 和 make xconfig)。
这些配置工具都是使用脚本语言,如 Tcl/TK、Perl 编写的(也包含一些用 C 编写的代码)。本文并不是对配置系统本身进行分析,而是介绍如何使用配置系统。所以,除非是配置系统的维护者,一般的内核开发者无须了解它们的原理,只需要知道如何编写 Makefile 和配置文件就可以。
makefile menuconfig过程讲解
当我们在执行make menuconfig这个命令时,系统到底帮我们做了哪些工作呢?
这里面一共涉及到了一下几个文件我们来一一讲解
Linux内核根目录下的scripts文件夹
arch/$ARCH/Kconfig文件、各层目录下的Kconfig文件
Linux内核根目录下的makefile文件、各层目录下的makefile文件
Linux内核根目录下的的.config文件、arm/$ARCH/下的config文件
Linux内核根目录下的 include/generated/autoconf.h文件
1、scripts文件夹存放的是跟make menuconfig配置界面的图形绘制相关的文件,我们作为使用者无需关心这个文件夹的内容
2、读取arch/arch/$ARCH/Kconfig以及各子目录下的Kcondig文件,生成配置条目。
$ARCH由linux内核根目录下的makefile文件决定
Kconfig文件中为配置信息的宏定义,与我们在make menuconfig图形界面看到的信息一致。
例如:
config CPU_S3C2410_DMA
bool
depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
default y if CPU_S3C2410 || CPU_S3C2442
help
DMA device selection for S3C2410 and compatible CPUs
因此,Kconfig文件很重要的作用就是:定义配置宏、相关依赖关系、帮助信息
3、读取内核根目录下.config文件,生成配置选项:[*]编译进内核 [M]编译为模块 [ ]不编译
arch/arm/configs/文件夹下存放了一些配置模板
我们可以通过cp /arch/arm/configs/xx_defconfig .config来使用这些配置模板
通过图形界面变更配置选项会自动更新到.config文件中
make disclean 会删除.config
4、编译过程根据.config生成 Linux内核根目录下的 include/config/auto.conf文件
CONFIG_EEPROM_93CX6=m
CONFIG_DM9000=y
根目录Makefile以及子目录的Makefile根据auto.conf生成编译条件
obj-$(CONFIG_DM9000) += dm9000.o //obj-m += dm9000.o
5、编译过程根据.config生成Linux内核根目录下的 include/linux/autoconf.h文件
.config 或 auto.conf 中定义要编译为 m 模块的项,如:
CONFIG_DEBUG_NX_TEST=m
在 autoconf.h 中会被定义为:
#define CONFIG_DEBUG_NX_TEST_MODULE 1
.config或auto.conf 中定义为编译为 y 的选项,如:
CONFIG_DM9000= y
在 autoconf.h 中会被定义为:
#define CONFIG_DM9000 1
autoconf.h中是.config或者auto.conf中配置信息的另一种体现形式,它是站在源码的角度,供源码使用的C语言宏定义。
6、总结
我们在使用make menuconfig时,首先会确定架构arch,然后读取arch目录的Kconfig中的配置宏定义,生成编译条目,然后读取Linux内核根目录下的.config选项, 将.config中的配置信息显示在图形界面上[*] [M] or []。我们在图形界面中更改配置选项会自动保存到.config文件中。编译过程根据.config随后生成auto.conf文件,它决定了makefile中各个文件的编译类型,静态编译进内核、编译成模块、不编译;同时生成autoconf.h,它以C语言宏定义的形式表达了 各个文件是否被编译,源码中会判断某文件是否被编译进行不同的处理。
示例1
1. 构建测试模块:hello
1.1 在linux-3.4/drivers/下新建目录hello
cd linux-3.4/drivers/
mkdir hello
1.2 在hello/下新建hello.c Makefile Kconfig三个文件
hello.c:
#include <linux/module.h> //所有模块都需要的头文件
#include <linux/init.h> // init&exit相关宏
#include <linux/kernel.h>
static int __init hello_init(void)
{
printk(KERN_WARNING "hello world.\n");
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_WARNING "hello exit!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("baoli");
MODULE_DESCRIPTION("hello world module");
Makefile:
obj-$(CONFIG_HELLO) += hello.o
Kconfig:
menu "HELLO TEST Driver "
comment "HELLO TEST Driver Config"
config HELLO
tristate "hello module test"
default m
help
This is the hello test driver --by baoli.
endmenu
1.3 修改上一级目录的Kconfig和Makefile
进入linux-3.4/drivers/
1)编辑Makefile,在后面添加一行:
obj-$(CONFIG_HELLO) += hello/
2)编辑Kconfig,在后面添加一行:
source "drivers/hello/Kconfig"
注:某些内核版本需要同时在arch/arm/Kconfig中添加:source “drivers/hello/Kconfig”
2. make menuconfig配置
1)执行:make menuconfig ARCH=arm
2)选择并进入:Device Drivers选项
可以看到新增 HELLO TEST Driver选项
3)进入 HELLO TEST Driver选项
可以选择 ,分别为编译成内核模块、编译进内核、不编译。
3. 编译
make zImage
编译内核,生成内核映像文件
1)如果选择编译成模块
编译内核过程中,会有如下输出:
LD drivers/hello/built-in.o
CC [M] drivers/hello/hello.o
CC drivers/hello/hello.mod.o
LD [M] drivers/hello/hello.ko
2)如果选择编译进内核
编译内核过程中,会有如下输出:
CC drivers/hello/hello.o
LD drivers/hello/built-in.o
编译完成后,drivers/hello/下新增hello.o和hello.ko,并且/linux-3.4/output/lib/modules/3.4.39/下也会有hello.ko。
4. 分析
1 source "drivers/hello/Kconfig"
在Kconfig中有类似语句:source “drivers/hello/Kconfig”
内核源码目录树中每一个Kconfig都会用source引入其所有子目录下的Kconfig,从而保证了所有的Kconfig项目都被包含进menuconfig中。这个也说明了:如果你自己在linux内核中添加了一个文件夹,一定要在这个文件夹下创建一个Kconfig文件,然后在这个文件夹的上一层目录的Kconfig中source引入这个文件夹下的Kconfig文件。
2 depends on
意思是本配置项依赖于另一个配置项。如果那个依赖的配置项为Y或者M,则本配置项才有意义;如果依赖的哪个配置项本身被设置为N,则本配置项根本没有意义。depends项会导致make menuconfig的时候找不到一些配置项。所以在menuconfig中如果找不到一个选项,但是这个选项在Kconfig中却是有的,则可能的原因就是这个配置项依赖的一个配置项是不成立的。depends依赖的配置项可以是多个,还可以有逻辑运算。这种时候只要依赖项目运算式子的结果为真则依赖就成立。
3 comment
用于定义一些帮助信息,出现在界面的第一行。
4 menu/endmenu menuconfig
1)menu用于生成菜单,其格式如下:
menu "Floating poing emulation"
config FPE_NWFPE
config FPE_NWFPE_XP
.............
endmenu
menu之后的Floating poing emulation是菜单名,menu和endmenu间有很多config条目,在配置界面中如下所示:
Floating poing emulation—>
[] FPE_NWFPE
[] FPE_NWFPE_XP
2)menuconfig有点类似menu,但区别就在于menu后面多了一个config,这个menu是可以配置的,如下图倒数第二行,前面比 menu类型多了一个<>,通过空格可以修改这个配置项的选中状态。而且从格式上来看,也是有区别的。格式如init/Kconfig中1131行:
menuconfig MODULES
tristate "Enable loadable module support"config
if MODULES
xx
endif
也就是说,配置项是位于if和endif中。其中的部分就是MODULES子目录显示的内容。如果选中了MODULE,那么if和endif中的内容可以显示。如果没有定义,就只能进入一个空目录。
可以认为是menu和config的结合体,既在前面有选项,回车后也可以展开。
5 config
config是构成Kconfig的最基本单元,其中定义了配置项的详细信息。
- 每个config菜单项都要有类型定义: bool布尔类型、 tristate三态(内建、模块、移除)、string字符串、 hex十六进制、 int整型。
例如:
config HELLO_MODULE
bool "hello test module"
bool 类型的只能选中或不选中,显示为[ ];
tristate类型的菜单项多了编译成内核模块的选项,显示为< > , 假如选择编译成内核模块,则会在.config中生成一个 CONFIG_HELLO_MODULE=m的配置,假如选择内建,就是直接编译成内核镜像,就会在.config中生成一个 CONFIG_HELLO_MODULE=y的配置。
- default:默认值
比如config类型是tristate,则默认值可以是y 、m、n。
6 Kconfig和.config文件和Makefile三者的关联
经过menuconfig配置之后保存,就会在内核顶层目录下生成.config文件。
=y表示该配置将会被编译进内核,=m表示该配置需要单独编译成模块。
内核顶层makefile会调用.config文件,引用.config里的配置,进而选择性的编译内核驱动模块。
配置项被配置成Y、N、M会影响“.config”文件中的CONFIG_XXX变量的配置值。“.config”中的配置值(=y、=m、没有)会影响最终的编译链接过程。如果=y则会被编入(built-in),如果=m会被单独连接成一个”.ko”模块,如果没有则对应的代码不会被编译。那么这是怎么实现的?都是通过makefile实现的。
如makefile中:obj-$(CONFIG_DM9000) += dm9000.o,
如果CONFIG_DM9000变量值为y,则obj += dm9000.o,因此dm9000.c会被编译;如果CONFIG_DM9000变量未定义,则dm9000.c不会被编译。如果CONFIG_DM9000变量的值为m则会被连接成“.ko”模块。
示例2
修改设备树
sdxprairie.dtsi修改
ra8900@32{
compatible = "epson,ra8900";
reg = <0x32>;
status = "ok";
};
reg = <0x32>由芯片手册中决定。This RTC’s slave address is [0110 010*].
不需要配置中断引脚,INT引脚电平由高变低表示中断发生,MCU检测到电平为低唤醒。
该设备节点需要挂载到I2C-3总线下。由i2cdetect -y -r 3可以探测I2C-3总线下的挂载情况。
增加RA8900驱动
1、添加rtc-ra8900.c文件
将rtc-ra8900.c文件复制到ql-ol-kernel/drivers/rtc目录下,并修改rtc-ra8900.c文件权限。
2、修改驱动文件所在路径下的Kconfig 文件
在comment "I2C RTC drivers"菜单下添加如下内容:
config RTC_DRV_RA8900
tristate "Epson RA8900CE"
help
If you say yes here you get support for the Epson
RA8900CE RTC chips.
This driver can also be built as a module. If so, the module
will be called rtc-ra8900.
3、修改驱动文件所在路径下的Makefile 文件
obj-$(CONFIG_RTC_DRV_RA8900) += rtc-ra8900.o
4、make kernel
编译过程中会提示有关RA8900的编译配置选项[N/m/y],输入y后,发现
ql-ol-kernel/build/.config下自动添加RA8900的编译配置。
CONFIG_RTC_DRV_RA8900=y
autoconfig.h 自动添加 #define CONFIG_HELLO 1
auto.conf 自动添加 CONFIG_HELLO=y
如果想将RA8900驱动编译成.ko文件,直接修改ql-ol-kernel/build/.config文件,
CONFIG_RTC_DRV_RA8900=m
然后编译即可。
ql-ol-kernel/build/.config文件是make menuconfig生成。具体是执行make O=build menuconfig生成的。由根目录下的Makefile 文件决定。
export QL_KERNEL_CONFIG=sa515m-perf_defconfig
export QL_DEBUG_KERNEL_CONFIG=sa515m_defconfig
kernel_menuconfig:
cd $(QL_KERNEL_DIR) ; make ARCH=${QL_ARCH} ${QL_KERNEL_CONFIG} O=build ;
debug_kernel_menuconfig:
cd $(QL_KERNEL_DIR) ; make ARCH=${QL_ARCH} ${QL_DEBUG_KERNEL_CONFIG} menuconfig O=build ;
参考:
https://blog.csdn.net/lizuobin2/article/details/51429937
https://blog.csdn.net/zhengmeifu/article/details/7682373
https://blog.csdn.net/weixin_42868654/article/details/88673366