概要:本文内容包含Linux源码树结构剖析、LinuxMakefile剖析、Kconfig文件剖析、Linux内核配置选项剖析。这种知识是为了理解内核文件的组织方式,为具体移植内核做打算。
一,Linux源码树结构剖析
对Linux源码树下个子目录内包含的内容进行列表列举:
更多Linux内核视频教程文档资料免费发放后台私信【内核】自行获取。
内核学习网站:
Linux内核源码/显存调优/文件系统/进程管理/设备驱动/网路合同栈-学习视频教程-腾讯课堂
二,LinuxMakefile剖析
主要从三个方面讲解:编译什么文件、如何编译文件、如何联接文件
最权威的参考资料:/Documentation/Kbuild/makefiles.txt
LinuxMakefile的分类:
编译什么文件
顶楼Makefile决定什么目录中的文件将编译进内核
init-y := init/
drivers-y := drivers/ sound/ firmware/
net-y := net/
libs-y := lib/
core-y := usr/
...
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
顶楼Makefile将13个子目录分成5个部份:init-y、drivers-y、net-y、libs-y、core-y顶楼通过下述句子包含和体系构架有关的Makefile。仔细观察可以看见/arch子目录的根目录下是没有Makefile文件的,而其它各子目录都是有Makefile。
include $(srctree)/arch/$(SRCARCH)/Makefile
...
SRCARCH := $(ARCH)
所以在编译内核之前先要确定ARCH:
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
...
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/
-e s/arm.*/arm/ -e s/sa110/arm/
-e s/s390x/s390/ -e s/parisc64/parisc/
-e s/ppc.*/powerpc/ -e s/mips.*/mips/
-e s/sh[234].*/sh/ )
默认的ARCH不是我们须要的,所以要进行更改:
ARCH ?= arm
CROSS_COMPILE ?=arm-linux-
$(srctree)/arch/$(SRCARCH)/Makefile对内核的内容进行了扩展
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y += $(machdirs) $(platdirs)
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
core-$(CONFIG_VFP) += arch/arm/vfp/
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
libs-y := arch/arm/lib/ $(libs-y)
...
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
可以看见一个新元素head-y,它还有一个特殊的地方,它是直接对应着两个文件,而不是目录。之所以分成两个是为了同时支持有无MMU的CPU,它们对应着两个不同的head$(MMUEXT).o文件,由变量MMUEXT控制,可以在配置时设定。
至此我们晓得了编译时将步入什么文件进行编译。编译时依次步入init-y、core-y、libs-y、drivers-y、net-y中列的目录调用其中的Makefile进行编译,每一个子目录还会生成build-in.o(libs-y所列的目录下有可能生成lib.a)。最后head-y列举的文件和build-in.o、lib.a一起联接成vmlinux.
在配置内核时,将会形成.config文件,Makefile将会在.config文件中添加下边两行。
CONFIG_KERNELVERSION = "2.6.32.2"
CONFIG_ARCH = "arm"
有可能是版本诱因linux内核24版源代码分析大全(清晰版),在2.6.32.2版本中并没有前面两个句子,有下边两句。
#Linux kernel version = 2.6.32.2
CONFIG_ARM = y
观察.config文件会发觉变量的值主要有两种y、m,各级的Makefile将会按照这种变量的值来决定编译什么文件,同时是编译进内核,还是作为内核模块存在。
obj-y中定义的.o文件将由当前目录下的.c、.S文件及子目录下的build-in.o文件编译联接得到的。
注意:obj-y中定义的.o文件的次序是有意义的。
下边是一段取自子目录中的Makefile文件内容,在该目录下有ioat和ipu子目录
obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
obj-$(CONFIG_NET_DMA) += iovlock.o
obj-$(CONFIG_DMATEST) += dmatest.o
obj-$(CONFIG_INTEL_IOATDMA) += ioat/
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o
obj-$(CONFIG_MV_XOR) += mv_xor.o
obj-$(CONFIG_DW_DMAC) += dw_dmac.o
obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
obj-$(CONFIG_MX3_IPU) += ipu/
obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
obj-$(CONFIG_SH_DMAE) += shdma.o
obj-m中定义的.o文件是由的当前目录下的.c、.S文件编译生成,它们不会与build-in.o一起编译步入内核。而是被编译成.ko文件,作为模块存在。
当.o文件由单个文件编译而成时,用下边的句子:
obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
当.o文件由多种文件编译而成时,用下边的句子:
obj-$(CONFIG_ISDN) +=isdn.o
isdn-objs := isdn_net_lib.o isdn_v110.o isdn_commen.o
编撰驱动程序时,也是以这些方法编撰Makefile。lib-y中定义的.o文件是由的当前目录下的.c、.S文件编译生成,她们被打包成当前目录下的lib.a文件。同时出现在lib-y和obj-y中的文件,不会被包含进lib.a文件。obj-y和obj-m可以拿来指定步入下一级目录。
如何编译那些文件
如何编译文件就是意味着编译选项和联接选项是哪些。
这种选项分成3类:全局的(适用整个代码树)、局部的(适用单个Makefile)、个体的(适用单个文件)。
全局选项是在顶楼Makefile和arch/$(ARCH)/Makefile中定义的,这种选项是CFLAGS、AFLAGS、LDFLAGS、ARFLAGS,它们分别是编译C文件的选项,编译汇编文件的选项linux内核24版源代码分析大全(清晰版),联接文件的选项,制做库文件的选项。
局部选项在各自子目录中定义,名称为:EXTRA_CFLAGS、EXTRA_AFALGS、EXTRA_LDFALGS、EXTRA_ARFLAGS.
对单文件设定编译选项,可以用CLFAGS_$@、AFLAGS_$@,后者对C文件,前者对汇编文件。
注意:3类选项是一起使用的,在scripts/Makefile.lib中可以见到:
_c_flags=$(CFLAGS)$(EXTRA_CFLGAS)$(CFALGS_$(baseterget.o))
怎么联接文件
在顶楼Makefile文件中有如下句子:
init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
可以看出之后的联接是相当于这五种built-in.o文件和head-o文件的联接。
然后对那些文件再度进行合并
vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds
可以看出初始化代码由两部份组成head-y和init-y两部份组成,但是head-y是在init-y的后面。所以总的代码次序是arch/arm/kernel/head.o(假定有MMU,没有的话是head_nommu.o)、arch/arm/kernel/init_task.o、init/build-in.o。
联接脚本是arch/$(SRCARCH)/kernel/vmlinux.lds,它由arch/$(SRCARCH)/kernel/vmlinux.lds.S生成。具体联接细节可以查看里面的文件内容。
三,内核的Kconfig剖析
内核配置工具读取各个Kconfig文件,生成配置界面共开放人员配置内核,最后生成配置文件.config。
关于Kconfig的最权威资料在/Documentations/Kbuild/kconfig-language.txt
Kconfig句型剖析:
Kconfig的基本要素:config
config常常被其它条目包含,拿来生成菜单和多项选择。
config JFFS2_FS_WBUF_VERIFY
bool "Verify JFFS2 write-buffer reads"
depends on JFFS2_FS_WRITEBUFFER
default n
help
This causes JFFS2 to read back every page written through the
write-buffer, and check for errors.
上述代码是config的常用方法:
config JFFS2_FS_WBUF_VERIFY
在配置界面中配置了该选项后,会在.config中出现CONFIG_JFFS2_FS_WBUF_VERIFY=y或则m.
bool "Verify JFFS2 write-buffer reads"
在配置界面上将会显示VerifyJFFS2write-bufferreads选项,bool是变量的类型,一共有5种变量类型:bool、tristate、string、hex、int,bool变量有两种取值y,m;tristate变量有三种取值y,m,n;string可以取字符串;hex取十六补码数;int取十补码数。
depends on JFFS2_FS_WRITEBUFFER
代表只有在JFFS2_FS_WRITEBUFFER被配置时红帽子linux下载,就会进行该选项的配置。
default n
代表默认的情况下是选择n
select FS_POSIX_ACL
代表在该选项被选种时,会将FS_POSIX_ACL也选种。
help
This causes JFFS2 to read back every page written through the
write-buffer, and check for errors.
当在配置时按H时会显示该信息。
menu条目
配置界面的主界面是由根目录下Makefile中ARCH配置决定的,当选择arm时,/arch/arm中的Kconfig文件将会拿来生成主目录。
下边的内容摘自/arch/arm/Kconfig
mainmenu "Linux Kernel Configuration"
设定主目录的名称
menu "System Type"
将会创建SystemType子目录
choice条目
choice将多个类似的配置选项组合在一起,供用户多选和单选
choice
prompt "Memory split"
default VMSPLIT_3G
help
Select the desired split between kernel and user memory.
If you are not absolutely sure what you are doing, leave this
option alone!
config VMSPLIT_3G
bool "3G/1G user/kernel split"
config VMSPLIT_2G
bool "2G/2G user/kernel split"
config VMSPLIT_1G
bool "1G/3G user/kernel split"
endchoice
prompt "Memory split"
上述代码给出提示信息,选中以后就可以进行选择配置
choice条目中定义的变量类型只能是bool和tristate,当配置的代码编译入内核时为bool,只能有一个条目选择为y;当编译成模块时为tristate或bool,为bool时,也只能是一个为y,当为tristate时,可以有多个m。
comment条目
comment条目用于提供帮助信息,出现在配置界面的第一行。
comment"Atleastoneemulationmustbeselected"
source条目
用于包含其他Kconfig文件
source "drivers/cpuidle/Kconfig"
菜单方式的配置界面的操作方式
配置界面中[*]、、[]分别表示相应的文件被编译进内核、编译成模块、没有被编译。
Load an Alertnate Configuration File
Save an Alertnate Configuration File
当执行第一条句子时,将.config外的config文件加载,当执行第二条时,表示储存成处.config外的config文件。
四,Linux内核配置选项
与移植密切相关的内容是SystemType、DeviceDriver。
内核配置主界面内容:
在配置内核的时侯依照次序进行linux 论坛,由于上面的配置会影响前面的。
原文链接:https://blog.csdn.net/u010909352/article/details/46375373