linux内核的配置机制及其编译过程

配置系统的基本结构

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的最基本单元,其中定义了配置项的详细信息。

  1. 每个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的配置。

  1. 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值