编译出uboot可以运行的linux内核代码的命令是make uImage,下面详细介绍下生成linux-2.6.22.6/arch/arm/boot/uImage的过程:
1、vmlinux、Image、uImage、zImage的区别
2、vmlinux生成过程简介
3、uImage生成过程简介
1、vmlinux、Image、uImage、zImage的区别,在执行make uImage之后会在%生成如下几个文件Image、uImage、zImage。
vmlinux是可引导的、压缩的内核。“vm”代表“Virtual Memory”。Linux 支持虚拟内存,不像老的操作系统比如DOS有640KB内存的限制。Linux能够使用硬盘空间作为虚拟内存,因此得名“vm”。它是elf格式的文件, 编译内核首先生成的是vmlinux,其它的文件都是基于此生成的。
Image是vmlinux经过OBJCOPY后生成的纯二进制映像文件
zImage是Image经过压缩后形成的一种映像压缩文件
uImage是在zImage基础上在前面64字节加上内核信息后的映像压缩文件,供uboot使用。可以从文件大小看到1848724-1848660=64字节
2、vmlinux生成过程简介,make uImage之后最先生成的是vmlinux,因为uImage依赖于vmlinux,在linux-2.6.22.6/arch/arm/Makefile下面有uImage这个目标,可以看到它依赖于vmlinux,所以先要分析vmlinux的生成过程
227 zImage Image xipImage bootpImage uImage: vmlinux
228 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
在linux-2.6.22.6/Makefile顶层Makefile下,定义了vmlinux这个目标
复制代码
745 vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
746 ifdef CONFIG_HEADERS_CHECK
747 $(Q)$(MAKE) -f $(srctree)/Makefile headers_check
748 endif
749 $(call if_changed_rule,vmlinux__)
750 $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
751 $(Q)rm -f .old_version
复制代码
先逐个分析她的依赖vmlinux-lds、vmlinux-init、vmlinux-main、kallsyms.o、FORCE
1)、vmlinux-lds,它是一个链接脚本在链接的时候使用,它跟体系结构相关
611 vmlinux-lds := arch/$(ARCH)/kernel/vmlinux.lds
arch/$(ARCH)/kernel/vmlinux.lds一开始是不存在的,它依赖于$(vmlinux-dirs)
755 $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
vmlinux-dirs这个变量是产生子目录下built-in.o文件的根源,这个在Linux移植之子目录下的built-in.o生成过程分析会介绍。
2)、vmlinux-init := $(head-y) $(init-y),其中head-y被定义在linux-2.6.22.6/arch/arm/Makefile中:
94 head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
init-y被定义在顶层Makefile中:
434 init-y := init/
573 init-y := $(patsubst %/, %/built-in.o, $(init-y))
patsubst是Makefile的函数,意思是找到符合%/格式的,然后以%/built-in.o替换,所以最终init-y = init/built-in.o
所以vmlinux-init = arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o
3)、vmlinux-main被定义在顶层的Makefile中
609 vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
类似与vmlinux-init的分析,最终vmlinux-main = usr/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o lib/lib.a lib/built-in.o drivers/built-in.o sound/built-in.o net/built-in.o
4)、kallsyms.o被定义在顶层的Makefile中
复制代码
679 ifdef CONFIG_KALLSYMS_EXTRA_PASS
680 last_kallsyms := 3
681 else
682 last_kallsyms := 2
683 endif
684
685 kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
复制代码
顶层的Makefile会包含配置好的.config文件
192 KCONFIG_CONFIG ?= .config
经查看CONFIG_KALLSYMS_EXTRA_PASS在.config没有设置,所以last_kallsyms := 3
62 # CONFIG_KALLSYMS_EXTRA_PASS is not set
最终kallsyms.o = .tmp_kallsyms2.o
接着寻找.tmp_kallsyms2.o,同样在顶层Makefile中
713 .tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
714 $(call if_changed_dep,as_o_S)
$(call if_changed_dep,as_o_S)当这条规则被使用时它将检查哪些文件需要更新,或命令行被改变。同时它会重新检测依赖关系的改变并将生成新的依赖文件。所以这里是检查.o、.S、scripts文件是否被更新过。
scripts的定义如下:
429 PHONY += scripts
430 scripts: scripts_basic include/config/auto.conf
431 $(Q)$(MAKE) $(build)=$(@)
总结一下kallsyms.o依赖的作用就是检测以下所有生产vmlinux相关的文件是否更新过。
5)、FORCE在Linux移植之配置过程分析已经介绍过,每次执行的时候都认为这个变量是最新的
6)、因为CONFIG_HEADERS_CHECK在.config中没有找到,所以执行的规则为:
749 $(call if_changed_rule,vmlinux__)
750 $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
751 $(Q)rm -f .old_version
$(call if_changed_rule,vmlinux__)检查规则是否被改变。它的意思是调用if_changed_rule函数,函数参数为$(1)=vmlinux__。具体分析参考https://blog.csdn.net/zxygww/article/details/50249531。它被定义在linux-2.6.22.6scriptsKbuild.include中
183 if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ),
184 @set -e;
185 $(rule_$(1)))
这段话的意思是if_changed 函数在当发现规则的依赖有更新,或者是对应目标的命令行参数发生改变时($(if strip $(any-prereq) $(arg-check)) 语句结果不为空),执行后面的语句。set -e 表示如果命令执行有错那么命令停止执行并退出。接着执行 $(cmd_$(1) 里的命令rule_vmlinux__:它在顶层Makefile定义为一个shell脚本调用
复制代码
634 define rule_vmlinux__
635 :
636 $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
637
638 $(call cmd,vmlinux__)
639 $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
640
641 $(Q)$(if $($(quiet)cmd_sysmap),
642 echo ' $($(quiet)cmd_sysmap) System.map' &&)
643 $(cmd_sysmap) $@ System.map;
644 if [ $$? -ne 0 ]; then
645 rm -f $@;
646 /bin/false;
647 fi;
648 $(verify_kallsyms)
649 endef
复制代码
将上述内容实际打印出来得到,在编译内核时需要输入make V=1才能显示完整的内核编译信息。
复制代码
set -e; if [ ! -r .version ]; then rm -f .version; echo 1 >.version; else mv .version .old_version; expr 0$(cat .old_version) + 1 >.version; fi; make -f scripts/Makefile.build obj=init
CHK include/linux/compile.h
/bin/bash /work/system/linux-2.6.22.6/scripts/mkcompile_h include/linux/compile.h
'arm' '' '' 'arm-linux-gcc -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -marm -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mapcs-32 -mno-thumb-interwork -D__LINUX_ARM_ARCH__=4 -march=armv4t -mtune=arm9tdmi -malignment-traps -msoft-float -Uarm -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -Wdeclaration-after-statement '
UPD include/linux/compile.h
arm-linux-gcc -Wp,-MD,init/.version.o.d -nostdinc -isystem /work/tools/gcc-3.4.5-glibc-2.3.6/lib/gcc/arm-linux/3.4.5/include -D__KERNEL__ -Iinclude -include include/linux/autoconf.h -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -marm -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mapcs-32 -mno-thumb-interwork -D__LINUX_ARM_ARCH__=4 -march=armv4t -mtune=arm9tdmi -malignment-traps -msoft-float -Uarm -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -Wdeclaration-after-statement -D'KBUILD_STR(s)=#s' -D'KBUILD_BASENAME=KBUILD_STR(version)' -D'KBUILD_MODNAME=KBUILD_STR(version)' -c -o init/version.o init/version.c
arm-linux-ld -EL -r -o init/built-in.o init/main.o init/version.o init/mounts.o init/initramfs.o init/calibrate.o
arm-linux-ld -EL -p --no-undefined -X -o .tmp_vmlinux1 -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o --start-group usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o arch/arm/mach-s3c2410/built-in.o arch/arm/mach-s3c2400/built-in.o arch/arm/mach-s3c2412/built-in.o arch/arm/mach-s3c2440/built-in.o arch/arm/mach-s3c2442/built-in.o arch/arm/mach-s3c2443/built-in.o arch/arm/nwfpe/built-in.o arch/arm/plat-s3c24xx/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o net/built-in.o --end-group
echo 'cmd_.tmp_vmlinux1 := arm-linux-ld -EL -p --no-undefined -X -o .tmp_vmlinux1 -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o --start-group usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o arch/arm/mach-s3c2410/built-in.o arch/arm/mach-s3c2400/built-in.o arch/arm/mach-s3c2412/built-in.o arch/arm/mach-s3c2440/built-in.o arch/arm/mach-s3c2442/built-in.o arch/arm/mach-s3c2443/built-in.o arch/arm/nwfpe/built-in.o arch/arm/plat-s3c24xx/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o net/built-in.o --end-group ' > ./..tmp_vmlinux1.cmd
相关文章