Linux内核编译
1、Linux内核的配置与编译:
1.配置内核
1)导出默认配置:
makexxxx_defconfig
注1:xxxx表示内核支持的芯片名称,如makeexynos_defconfig
注2:每个支持的芯片在内核源码中都有默认配置,而默认配置很少只能保证系统完成最基本的功能
注3:可以通过直接更改.config文件来配置内核(麻烦),所有内核配置的本质都是更改.config文件
注4:配置文件中的xxxx=y表示添加该功能,注释表示不添加该功能(减少内核体积)
2)更改配置(内核提供了几种简单的配置方法,其本质就是更改.config文件中的配置)
makegconfig 依赖 GTK 库
makexconfig 依赖于 QT 库
makeconfig 麻烦
->makemenuconfig
选定状态开关:空格
搜索一个选项:/
[ ] 有两种状态。
输入Y,显示为“*”,表示该函数在内核中被选中,相关函数代码将被编译到内核中。
输入N,显示为空,说明内核中没有选择该函数。
<>有三种状态
输入Y,显示为“*”,表示选择内核中的函数
输入N,显示为空源码包编译方法,说明内核中没有选择该函数
输入M,会显示为“M”,说明选择内核中的函数作为模块(编译后与内核镜像不在同一个文件中)
2.编译内核
makeuImage编译内核镜像(将选项选为“*”编译到内核)
makemodules 编译内核模块(编译选项选为“M”)
makedtbs编译设备树文件(使驱动程序和设备之间的关系变得完美的文件)
makeclean 删除文件
2.向内核添加子菜单:
每级目录都包含一个Kconfig文件,用于生成可选菜单。 你可以根据Kconfig的句型改变相应的Kconfig文件,在菜单中添加自己的选项。在Kconfig文件中,menu就是本级菜单,比如菜单“Characterdevices”。 如果我们想在这个菜单下添加子菜单,可以按照句型添加在menu和endmenu之间。
句型:
configFS4412_LED#固定句型,configXXX、XXX用于与MakeFile关联,即配置后MakeFile会根据配置进行编译
三态“FS4412LEDDeviceSupport”
#tristate“菜单显示名称”; tristate表示该选项有三种状态(即可以选择N/Y/M),bool表示有两个选项[](N/Y)
默认值
#defaultn默认为'N',即不添加该功能defaulty默认添加defaultm默认编译成模块(重新配置后生效)
取决于 ARCH_EXYNOS4
#dependson 依赖菜单 未选择依赖选项时不显示此选项
帮助
supportleddeviceonFS4412developboard#帮助文档可选
详细信息请参考:文档/kbuild
要将您自己的模块添加到菜单中:
1.更改Kconfig添加子菜单
2.添加对应的.C文件(驱动文件)
3、更改相应的Makefile,将菜单与编译关联起来(编译驱动文件)
3、linux内核(uImage)的编译过程:
1、在顶层目录下执行makeuImage
2、顶层目录下的MakeFile
第155章
#srctree为当前MakeFile所在目录
198ARCH?=arm#自己改的
第203章
504include$(srctree)/arch/$(SRCARCH)/Makefile
->includearch/arm/MakeFile
-> 执行makeuImage后,会根据我们设置的CPU架构执行对应架构下的MakeFile
3. arch/arm/MakeFile
291boot:=拱/臂/启动
第299章
#uImage 是 BOOT_TARGETS 的成员
304$(BOOT_TARGETS):vmlinux
#生成uImage需要生成BOOT_TARGETS大目标
#依赖源码顶层目录中的vmlinux(编译时生成的文件)
第305章
#Q是@的封装,不输出编译信息
#MAKE是make-C的封装 -C表示切换到指定目录下的MakeFile
#$(build)=$(boot)->build=arch/arm/boot
#MACHINE=$(MACHINE)->MACHINE:=arch/arm/mach-exynos
#$(boot)/$@->arch/arm/boot/uImage
->make-Carch/arm/bootMACHINE=arch/arm/mach-exynosarch/arm/boot/uImage
->依赖顶层目录中的vmlinux,切换到arch/arm/boot下的MakeFile(参数为MACHINE)并执行,在arch/arm/boot/下生成目标uImage(uImage就在该目录下)
/********************机器变量的来源********************/
.config/291CONFIG_ARCH_EXYNOS=y
155机器-$(CONFIG_ARCH_EXYNOS)+=exynos
->.config 文件是在最初导出配置时形成的。 .config中仅包含形参CONFIG_ARCH_EXYNOS(其他已注释)
->machine-y+=exynos 表示 machine-y=exynos
232ifneq($(机器-y),)
#比较machine-y与空值(machine-y=exynos),不相等
233MACHINE:=arch/arm/mach-$(word1,$(machine-y))/#word1,$(machine-y)word 是一个函数,它从 machine-y 变量中获取第一个短语
->机器:=arch/arm/mach-exynos
/******************************************************** ***** ******************/
4. arch/arm/boot/Makefile
78$(obj)/uImage:$(obj)/zImageFORCE
#依赖zImageobj来表示当前MakeFile的路径。 FORCE强制编译,无论是否已编译。
79@$(check_for_multiple_loadaddr)
80$(callif_changed,uimage)
81@$(kecho)'Image$@isready'#输出信息
->依赖当前目录下的zImage生成uImage
-> 跟踪 zImage
30ifeq($(CONFIG_XIP_KERNEL),y)
#CONFIG_XIP_KERNEL 在.config中定义,无形参
41其他
54$(obj)/zImage:$(obj)/压缩/vmlinuxFORCE
#依赖arch/arm/boot/compressed/vmlinux(和之前的不一样)
55$(callif_changed,objcopy)
#使用gcc编译的程序都是elf格式,需要转换成二进制补码格式。
56@$(kecho)'内核:$@isready'#显示信息
51$(obj)/压缩/vmlinux:$(obj)/ImageFORCE
#vmlinux 依赖于 arch/arm/boot/Image
52$(Q)$(MAKE)$(build)=$(obj)/压缩$@
#make-Carch/arm/boot/compressedarch/arm/boot/compressed/vmlinux
->依赖arch/arm/boot/Image源码包编译方法,切换到arch/arm/boot/compressed/下的MakeFile生成vmlinux
/************机器参数参考********************/
拱/臂/启动/Makefile
14ifneq($(机器),)
在#arch/arm/MakeFile中传递参数,输入MACHINE=arch/arm/mach-exynos
15include$(srctree)/$(MACHINE)/Makefile.boot
#includearch/arm/mach-exynos/Makefile.boot
16 结束
arch/arm/mach-exynos/Makefile.boot
1zreladdr-y+=0x40008000
#内核入口地址(运行起始地址)
2params_phys-y:=0x40000100
#uboot和内核协商存储参数的位置。
拱/臂/启动/Makefile
22ZRELADDR:=$(zreladdr-y)
#ZRELADDR=0x40008000
23PARAMS_PHYS:=$(params_phys-y)
#PARAMS_PHYS=0x40000100
24INITRD_PHYS:=$(initrd_phys-y)
25
26exportZRELADDRINITRD_PHYSPARAMS_PHYS
#Import 使其在全球范围内可用
/******************************************************** ***** **************/
5.arch/arm/boot/压缩/MakeFile
185$(obj)/vmlinux:$(obj)/vmlinux.lds$(obj)/$(HEAD)$(obj)/piggy.$(suffix_y).o
186$(addprefix$(obj)/,$(OBJS))$(lib1funcs)$(ashldi3)
187$(bswapsdi2)强制
#vmlinux 依赖很多文件来形成
#依赖文件来源
#$(obj)/vmlinux.lds
#arch/arm/boot/compressed/vmlinux.lds链接脚本决定了elf文件(内核源文件)的布局
#$(obj)/$(HEAD)=arch/arm/boot/compressed/$(HEAD)
#25HEAD=head.o由head.S生成(内核源文件)
#$(obj)/piggy.$(suffix_y).o
#86suffix_$(CONFIG_KERNEL_GZIP)=gzip
#.config/40CONFIG_KERNEL_GZIP=y导出默认配置时配置的内核的压缩格式
#->suffix_y=gzip
#->$(obj)/piggy.$(suffix_y).o=arch/arm/boot/compressed/piggy.gzip.o是由piggy.gzip.S生成的(编译时生成)
#$(addprefix$(obj)/,$(OBJS))#给变量$(OBJS)添加前缀$(addprefix$(obj)/)
#26OBJS+=misc.odecompress.o->OBJS=misc.odecompress.o
#->$(addprefix$(obj)/,$(OBJS))=arch/arm/boot/compressed/misc.odecompress.o由misc.cdecompress.c(内核源文件)生成
#这两个文件是用来解压内核的。 内核包含解压代码。
#$(lib1funcs)
#148lib1funcs=$(obj)/lib1funcs.o->lib1funcs=arch/arm/boot/compressed/lib1funcs.o(由lib1funcs.S生成)
#150$(obj)/lib1funcs.S:$(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S(内核源文件)
#$(ashldi3)
#154ashldi3=$(obj)/ashldi3.o->ashldi3=arch/arm/boot/compressed/ashldi3.o(ashldi3.S生成)
#156$(obj)/ashldi3.S:$(srctree)/arch/$(SRCARCH)/lib/ashldi3.S(内核源文件)
#$(bswapsdi2)
#160bswapsdi2=$(obj)/bswapsdi2.o->bswapsdi2=arch/arm/boot/compressed/bswapsdi2.o(由bswapsdi2.S生成)
#162$(obj)/bswapsdi2.S:$(srctree)/arch/$(SRCARCH)/lib/bswapsdi2.S(内核源文件)
/****************************piggy.gzip.o**************** ** ******************/
#195$(obj)/piggy.$(suffix_y).o:$(obj)/piggy.$(suffix_y)FORCE->piggy.gzip.o:piggy.gzip->piggy.gzip.o 取决于 Piggy。压缩包
#192$(obj)/piggy.$(suffix_y):$(obj)/../ImageFORCE->piggy.gzip:arch/arm/boot/ImageFORCE->piggy.gzip依赖下层目录下的Image
->返回下层目录跟踪arch/arm/boot/Image
/******************************************************** ***** **********************/
6.arch/arm/boot/MakeFile
47$(obj)/图片:vmlinuxFORCE
#依赖顶层源码下的vmlinuxFORCE来执行
48$(callif_changed,objcopy)
49@$(kecho)'内核:$@isready'
->返回顶层源码跟踪vmlinux
7.顶层目录MakeFile
817vmlinux:脚本/link-vmlinux.sh$(vmlinux-deps)强制
#scripts/link-vmlinux.sh 编译所需脚本
#809vmlinux-deps:=$(KBUILD_LDS)$(KBUILD_VMLINUX_INIT)$(KBUILD_VMLINUX_MAIN)
#追踪某些路径下的源文件
#802exportKBUILD_VMLINUX_INIT:=$(head-y)$(init-y)
#803exportKBUILD_VMLINUX_MAIN:=$(核心-y)$(库-y)$(驱动程序-y)$(网络-y)
#804exportKBUILD_LDS:=arch/$(SRCARCH)/kernel/vmlinux.lds
#链接脚本(两个链接过程)
倒序总结:uImage是zImage使用uboot中的工具在其上添加一个back来生成的。
zImage是由arch/arm/boot/compressed/vmlinux(elf格式)文件通过二进制补码格式转换生成的。
vmlinux是根据vmlinux.lds链接(二级链接)从/arch/arm/boot/compressed/piggy.gzip(压缩内核)和misc.c、decompress.c(用于解压内核的代码)生成的
piggy.gzip 是从 /arch/arm/boot/Image 文件(不包含解压代码的二进制补码内核文件)压缩而来的
Image文件是由源码顶层目录中的vmlinux(elf格式)进行二进制补码转换生成的。
vmlinux是基于链接脚本arch/arm/kernel/vmlinux.lds(一个链接)由一系列内核源代码和工具生成的
时序总结:按照arch/arm/kernel/vmlinux.lds和各级Makefile的规则编译一系列源码和工具,在源码顶层目录生成vmlinux(elf格式内核),这是第一个链接。
vmlinux通过二进制补码转换生成arch/arm/boot/Image(二进制补码格式的内核)
将Image文件压缩得到piggy.gzip文件(压缩二进制补码内核)(piggy.gzip文件需要解压才能运行)
Piggy.gzip和解压文件misc.c、decompress.c等的代码根据链接脚本arch/arm/boot/compressed/vmlinux.lds链接成一个文件(第二链接)vmlinux(elf)
通过二进制补码转换将vmlinux文件转换为zImage。
zImage通过添加回生成uImage
关于嵌入式物联网,确实有很多东西需要学习。 不要学错路线和内容,导致你错失薪资!
我免费给大家分享一个数据包,差不多150G。 以上学习内容、面试、项目都比较新、全面! 网上买一条鱼,恐怕起码要几十块。加莫莫发布信息