为解惑生成zImage的过程,查到此文,地址:http://blog.chinaunix.net/uid-26009923-id-3194580.html
分析一下make zImage的流程,具体的操作是:首先将linux-2.6.30.4/config_EmbedSky_W35_256MB改名为.config,然后make zImage.看一下make zImage之后发生了什么事情。
- linux-2.6.30.4/Makefile
- 284 #config-targets=0, mixed-targets=0, dot-config=1,不会进入L285
- 285 ifeq ($(mixed-targets),1) #不成立跳过
- ...
- 291 ifeq ($(config-targets),1) #不成立跳过
- 304 else
- 305
- 306 ifeq ($(KBUILD_EXTMOD),)
- ......
- 354 include $(srctree)/arch/$(SRCARCH)/Makefile
在 arch/arm/Makefile中包含了zImage
- linux-2.6.30.4/arch/arm/Makefile
- 174 ifeq ($(CONFIG_XIP_KERNEL),y)
- 175 KBUILD_IMAGE := xipImage
- 176 else
- 177 KBUILD_IMAGE := zImage
- 178 endif
- 179
- 180 all: $(KBUILD_IMAGE)
- 181
- 182 boot := arch/arm/boot
- 183
- 193 zImage Image xipImage bootpImage uImage: vmlinux
- 194 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
- #zImage依赖于vmliux, vmliux在linux-2.6.30.4/Makefile中
1. linux-2.6.30.4/Makefile 中包含了arch/arm/Makefile
2. 在 arch/arm/Makefile中找到目标zImage
3. zImage依赖linux-2.6.30.4中的Makefile中vmlinux
4. 分析 linux-2.6.30.4/Makefile中vmlinux的依赖
5.
就第4步进行具体分析
- 306 ifeq ($(KBUILD_EXTMOD),)
- 307 PHONY += scripts
- 308 scripts: scripts_basic include/config/auto.conf
- 309 $(Q)$(MAKE) $(build)=$(@)
- 310
- 311 init-y := init/
- 312 drivers-y := drivers/ sound/ firmware/
- 313 net-y := net/
- 314 libs-y := lib/
- 315 core-y := usr/
- 316 endif # KBUILD_EXTMOD
- 317
- 318 ifeq ($(dot-config),1)
- 319 -include include/config/auto.conf
- 320
- 321 ifeq ($(KBUILD_EXTMOD),)
- 322 -include include/config/auto.conf.cmd
- 323
- 324 $(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
- 325
- 326 include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
- 327 $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
- 328 else
- 329 PHONY += include/config/auto.conf
- 330
- 331 include/config/auto.conf:
- 332 $(Q)test -e include/linux/autoconf.h -a -e $@ || ( \
- 333 echo; \
- 334 echo " ERROR: Kernel configuration is invalid."; \
- 335 echo " include/linux/autoconf.h or $@ are missing."; \
- 336 echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \
- 337 echo; \
- 338 /bin/false)
- 339
- 340 endif # KBUILD_EXTMOD
-
- #vmliux的依赖vmlinux-lds=arch/arm/kernel/vmlinux.lds vmlinux-init=arch/arm/kernel/head-nommu.o arch/arm/ kernel/init_task.o init/built-in.o vmlinux-main= usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/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 firmware/built-in.o net/built-in.o kallsyms=
- 576 vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
- #vmlinux-lds等 依赖于vmlinux-dirs
- 598 $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
-
- 601 PHONY += $(vmlinux-dirs)
- 602 $(vmlinux-dirs): prepare scripts
- 603 $(Q)$(MAKE) $(build)=$@
-
- 636 prepare3: include/config/kernel.release
- 649
- 650 prepare2: prepare3 outputmakefile
- 651
- 652 prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h \
- 653 include/asm include/config/auto.conf
- 654 $(cmd_crmodverdir)
- 655
- 656 archprepare: prepare1 scripts_basic
- 657
- 658 prepare0: archprepare FORCE
- 659 $(Q)$(MAKE) $(build)=.
- 660 $(Q)$(MAKE) $(build)=. missing-syscalls
- 661
- 662 prepare: prepare0
- 整理一下上述的各个依赖关系,如下图所示
-

- 下面按照执行的顺序详细分析一下,各个步骤:
- 4.1 首先执行的是scripts的过程:
- 这个过程类似于make menuconfig的过程,只不过最后调用的是:conf -s ,不产生图形界面。
- scrpts的过程:
- 326 include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
- 327 $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
- 即: make -f /root/kernel/linux-2.6.30.4/Makefile silentoldconfig
- make -f scripts/Makefile.build obj=scripts/basic
- mkdir -p include/linux include/config
- make -f scripts/Makefile.build obj=scripts/kconfig silentoldconfig
- scripts/kconfig/conf -s arch/arm/Kconfig
- 4.2 其次执行的是prepare的过程:
-

-
- linux-2.6.30.4/Makefile 中archprepare: prepare1 scripts_basic
- 而在
- arch/arm/Makefile中archprepare: maketools
- 这地方有点没有看明白,在Makefile和arch/arm/Makefile中都有archprepare的规则,
- 什么这两个都执行了,而不是一个覆盖另一个?
-
- linux-2.6.30.4/Makefile
- 714 include/linux/version.h: $(srctree)/Makefile FORCE
- 715 $(call filechk,version.h)
- 这将会调用linux-2.6.30.4/scripts/Kbuild.include中的filechk函数,主要作用是:用Makefile中的版本信息更新include/linux/version.h中的版本信息。
-
- arch/arm/Makefile
- $(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
- 即: make -f scripts/Makefile.build obj=arch/arm/tools include/asm-arm/mach-types.h
- 这会调用arch/arm/tools/Makefile中的规则产生include/asm-arm/mach-types.h 文件
-
- linux-2.6.30.4/Makefile
- 628 include/config/kernel.release: include/config/auto.conf FORCE
- 629 $(Q)rm -f $@
- 630 $(Q)echo $(kernelrelease) > $@
- 这会产生kernel.release文件: echo 2.6.30.4-EmbedSky > include/config/kernel.release
-
- linux-2.6.30.4/Makefile
- 717 include/linux/utsrelease.h: include/config/kernel.release FORCE
- 718 $(call filechk,utsrelease.h)
- 这将会调用linux-2.6.30.4/scripts/Kbuild.include中的filechk函数,主要是检查include/config/kernel.release中的kernel版本信息是否超过64字节,超过则报错。
-
- linux-2.6.30.4/Makefile
- 693 include/asm: FORCE
- 694 $(Q)$(check-symlink)
- 695 $(Q)$(create-symlink)
- #刚生出来(下载)的内核代码是不存在include/asm目录的,check-symlink是检查include/asm是存在并指向asm-arm,如果不存在asm-arm的符号连接则创建,存在但不正确就打印出错信息。
-
- linux-2.6.30.4/Makefile
- prepare1的最后执行 $(cmd_crmodverdir)
- 1146 cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \
- 1147 $(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*)
- 即:mkdir -p .tmp_versions
-
- linux-2.6.30.4/Makefile
- archprepare的第二个依赖 scripts_basic
- 即:make -f scripts/Makefile.build obj=scripts/basic
-
- linux-2.6.30.4/Makefile
- prepare0的依赖执行完之后,执行:
- make -f scripts/Makefile.build obj=.
- #执行scripts/Makefile的__build目标,此处只执行always依赖,(KBUILD_BUILTIN=1,但是$(builtin-target) $(lib-target) $(extra-y)都为空,KBUILD_MODULES=0)
- always=./include/linux/bounds.h ./include/asm/asm-offsets.h
- __build: ./include/linux/bounds.h ./include/asm/asm-offsets.h
- :
- 这将会编译kernel/bounds.c 和 arch/arm/kernel/asm-offsets.c两个文件
4.3 vmlinux-dirs的依赖执行完了之后,再去执行vmlinux-dirs的命令了
- linux-2.6.30.4/Makefile
- 880 PHONY += $(vmlinux-dirs)
- 881 $(vmlinux-dirs): prepare scripts
- 882 $(Q)$(MAKE) $(build)=$@
- 由于命令中用到$@即vmlinux-dirs先转到vmlinux-dirs的定义处:
-
- linux-2.6.30.4/Makefile
- 653 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
- 654 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
- 655 $(net-y) $(net-m) $(libs-y) $(libs-m)))
- 可以看到vmlinux-dirs是:
- vmlinux-dirs=init usr arch/arm/kernel arch/arm/mm arch/arm/common arch/arm/mach-s3c2410 arch/arm/mach-s3c2400 arch/arm/mach-s3c2412 arch/arm/mach-s3c2440 arch/arm/mach-s3c2442 arch/arm/mach-s3c2443 arch/arm/plat-s3c24xx arch/arm/plat-s3c kernel mm fs ipc security crypto block drivers sound firmware net arch/arm/lib lib
- 这就是要去内核的每一个目录下面去编译需要的每一个源文件了
-
- make -f scripts/Makefile.build obj=init
- #builtin-target=init/built-in.o lib-target= extra-y= subdir-ym= always=
-
- linux-2.6.30.4/scripts/Makefile.build
- 93 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
- 94 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
- 95 $(subdir-ym) $(always)
- 96 @:
- #此时只有builtin-target=init/built-in.o有定义,下一步生成目标builtin-target
-
- linux-2.6.30.4/scripts/Makefile.build
- 286 ifdef builtin-target
- 287 quiet_cmd_link_o_target = LD $@
- 288 # If the list of objects to link is empty, just create an empty built-in.o
- 289 cmd_link_o_target = $(if $(strip $(obj-y)),\
- 290 $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \
- 291 $(cmd_secanalysis),\
- 292 rm -f $@; $(AR) rcs $@)
- 293
- 294 $(builtin-target): $(obj-y) FORCE
- 295 $(call if_changed,link_o_target)
-
- #先去执行builtin-target的依赖obj-y,将所以.c编译为.o, .s编译为.o
- obj-y=init/main.o init/version.o init/mounts.o init/noinitramfs.o init/calibrate.o
- ld
- 把obj-y链接成init/built-in.o
- 目标vmlinux-dirs执行完成后,built-in.o
-
- $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
- 因为这个指令是一个空指令,所以当vmlinux-dirs执行完成之后,vmlinux的依赖$(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds)都准备好了。
4.4 vmlinux的两个依赖: vmlinux.o与$(kallsyms.o)
- 4.4.1 vmlinux的一个依赖是:vmlinux.o
- linux-2.6.30.4/Makefile
- 866 vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE
- 867 $(call if_changed_rule,vmlinux-modpost)
-
- linux-2.6.30.4/scripts/Kbuild.include
- 208 if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \
- 209 @set -e; \
- 210 $(rule_$(1)))
- #如果目标有更新则执行rule_vmlinux-modpost
- linux-2.6.30.4/Makefile
- 838 define rule_vmlinux-modpost
- 839 :
- 840 +$(call cmd,vmlinux-modpost)
- 841 $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
- 842 $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
- 843 endef
-
- linux-2.6.30.4/Makefile
- 834 quiet_cmd_vmlinux-modpost = LD $@
- 835 cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ \
- 836 $(vmlinux-init) --start-group $(vmlinux-main) --end-group \
- 837 $(filter-out $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
- #首先链接生成vmlinux.o: L834 arm-linux-ld -EL -r -o vmlinux.o <target>
- 然后执行:make -f /root/kernel/linux-2.6.30.4/scripts/Makefile.modpost vmlinux.o,
- 最后把链接生成vmlinux.o的过程打印到.cmd文件中
-
- linux-2.6.30.4/scripts/Makefile.modpost
- 103 vmlinux.o: FORCE
- 104 @rm -fr $(kernelmarkersfile)
- 105 $(call cmd,kernel-mod)
- 然后执行:
- 101 cmd_kernel-mod = $(modpost) $@
- 即:scripts/mod/modpost -o /root/kernel/linux-2.6.30.4/Module.symvers -S -c vmlinux.o
- 用scripts/mod/modpost处理vmlinux.o,得到Module.symvers,这个具体有什么作用现在还没有搞清楚。
-
-
- 4.4.2 vmlinux的一个依赖是:$(kallsyms.o)=.tmp_kallsyms2.o
- 801 .tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
- 802 $(call if_changed_dep,as_o_S)
-
- .tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
- 依赖中又含有%.o: %.S ? 没看明白
- 看到打印中: /opt/EmbedSky/4.3.3/bin/arm-none-linux-gnueabi-nm -n .tmp_vmlinux2 | scripts/kallsyms > .tmp_kallsyms2.S
- 然后通过: arm-linux-gcc $(a_flags) -c -o .tmp_kallsyms2.o .tmp_kallsyms2.S
-
- linux-2.6.30.4/scripts/Kbuild.include
- 198 if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \
- 199 @set -e; \
- 200 $(echo-cmd) $(cmd_$(1)); \
- 201 scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\
- 202 rm -f $(depfile); \
- 203 mv -f $(dot-target).tmp $(dot-target).cmd)
-
- #执行cmd_as_o_S
- linux-2.6.30.4/scripts/Makefile
- 1580 cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
- 4.5 当vmlinux的所有依赖都ok之后,执行vmlinux的命令
- 845 # vmlinux image - including updated kernel symbols
- 846 vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
- 847 ifdef CONFIG_HEADERS_CHECK
- 848 $(Q)$(MAKE) -f $(srctree)/Makefile headers_check
- 849 endif
- 850 ifdef CONFIG_SAMPLES
- 851 $(Q)$(MAKE) $(build)=samples
- 852 endif
- 853 ifdef CONFIG_BUILD_DOCSRC
- 854 $(Q)$(MAKE) $(build)=Documentation
- 855 endif
- 856 $(call vmlinux-modpost)
- 857 $(call if_changed_rule,vmlinux__)
- 858 $(Q)rm -f .old_version
-
- #CONFIG_HEADERS_CHECK CONFIG_SAMPLES CONFIG_BUILD_DOCSRC都为空,所以
- 4.5.1 $(call vmlinux-modpost) ;没找到定义
- 4.5.2 $(call if_changed_rule,vmlinux__) ;具体分析
- 4.5.3 $(Q)rm -f .old_version
-
-
- linux-2.6.30.4/scripts/Kbuild.include
- 208 if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \
- 209 @set -e; \
- 210 $(rule_$(1)))
- #如果目标有更新则执行rule_vmlinux__
-
- linux-2.6.30.4/Makefile
- 731 define rule_vmlinux__
- 732 :
- 733 $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
- 734
- 735 $(call cmd,vmlinux__)
- 736 $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
- 737
- 738 $(Q)$(if $($(quiet)cmd_sysmap), \
- 739 echo ' $($(quiet)cmd_sysmap) System.map' &&) \
- 740 $(cmd_sysmap) $@ System.map; \
- 741 if [ $$? -ne 0 ]; then \
- 742 rm -f $@; \
- 743 /bin/false; \
- 744 fi;
- 745 $(verify_kallsyms)
- 746 endef
- L733行 CONFIG_KALLSYMS=y,所以不做任何操作
- L735行 在linux-2.6.30.4/scripts/Kbuild.include L160 cmd = @$(echo-cmd) $(cmd_$(1)),打印并执行cmd_vmlinux__
-
- linux-2.6.30.4/Makefile
- 704 quiet_cmd_vmlinux__ ?= LD $@
- 705 cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
- 706 -T $(vmlinux-lds) $(vmlinux-init) \
- 707 --start-group $(vmlinux-main) --end-group \
- 708 $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
- #链接生成vmlinux的过程:
- L735 arm-linux-ld <flags> -o vmlinux -Tarch/arm/kernel/vmlinux.lds <targets>
- L736 将链接生成vmlinux的过程写入到.cmd中
- L738 在linux-2.6.30.4/Makefile中 L724 cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
-
- .scripts/mksysmap System.map
- ./scripts/mksysmap vmlinux System.map
- if [ $? -ne 0 ];
- then rm -f vmlinux;
- /bin/false;
- fi
-
- L858 rm -f .old_version
5. 生成最终的zImage
- 终于zImage的依赖vmlinux执行完了,下面回到arch/arm/Makefile中执行zImge的命令过程:
- linux-2.6.30.4/arch/am/Makefile
- 230 zImage Image xipImage bootpImage uImage: vmlinux
- 231 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
- #make -f scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/mach-s3c2410/ arch/arm/boot/zImage
-
- #执行arch/arm/boot/Makefile中的zImage
- linux-2.6.30.4/arch/arm/boot/Makefile
- 56 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
- 57 $(call if_changed,objcopy)
- 58 @cp -f arch/arm/boot/zImage zImage.bin
- 59 @echo ' Kernel: $@ is ready'
- 首先生成arch/arm/boot/compress/vmlinux
-
- linux-2.6.30.4/arch/arm/boot/Makefile中
- 53 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
- 54 $(Q)$(MAKE) $(build)=$(obj)/compressed $@
- make -f scripts/Makefile.build obj=arch/arm/boot/compressed arch/arm/boot/compressed/vmlinux
-
- 执行arch/arm/boot/compress/Makefile
- linux-2.6.30.4/arch/arm/boot/compressed/Makefile
- 94 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
- 95 $(addprefix $(obj)/, $(OBJS)) FORCE
- 96 $(call if_changed,ld)
- 97 @:
-
- #arm-linux-gcc <flags> -c -o arch/arm/boot/compressed/head.o arch/arm/boot/compressed/head.S
- linux-2.6.30.4/arch/arm/boot/compressed/Makefile
- 102 $(obj)/piggy.o: $(obj)/piggy.gz FORCE
- gzip -f -9 < arch/arm/boot/compressed/../Image > arch/arm/boot/compressed/piggy.gz
- piggy.o
- #arm-linux-gcc <flags> -c -o arch/arm/boot/compressed/piggy.o arch/arm/boot/compressed/piggy.S
-
- #arm-linux-gcc <flags> -c -o arch/arm/boot/compressed/misc.o arch/arm/boot/compressed/misc.c
-
- #arm-linux-ld <ld_flags> -T arch/arm/boot/compressed/vmlinux.lds compressed/head.o piggy.o misc.o -o arch/arm/boot/compressed/vmlinux
-
- linux-2.6.30.4/arch/arm/boot/Makefile
- 56 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
- 57 $(call if_changed,objcopy)
- 58 @cp -f arch/arm/boot/zImage zImage.bin
- 59 @echo ' Kernel: $@ is ready'
- #好了compressed/vmlinux也生成了,最后一步$(call if_changed, objcopy)
-
- linux-2.6.30.4/scripts/Kbuild.include
- 192 if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
- 193 @set -e; \
- 194 $(echo-cmd) $(cmd_$(1)); \
- 195 echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
- #打印并执行$(cmd_objcopy),最后把$(cmd_objcopy)写到.cmd文件中
-
- linux-2.6.30.4/scripts/Makefile.lib
- 184 quiet_cmd_objcopy = OBJCOPY $@
- 185 cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
- 即:arm-linux-objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage
- 将vmlinux这个elf的二进制文件,转换为raw二进制文件。
终于完成了,zImage的过程,不容易啊!