查看: 1344|回复: 0

[经验] Arm linux 内核构建(2)

[复制链接]
  • TA的每日心情
    开心
    2018-2-7 14:55
  • 签到天数: 51 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2017-11-15 15:06:38 | 显示全部楼层 |阅读模式
    分享到:
    本文将继续讲解arm linux内核zImage的生成过程,内核版本号4.10。
    arch/arm/Makefile文件中,可以看到zImage 依赖于vmlinux,这里的vmlinux指的是根目录下的vmlinux
    arch/arm/Makefile:
    boot := arch/arm/boot
    BOOT_TARGETS    = zImage Image xipImage bootpImage uImage
    … …
    $(BOOT_TARGETS):vmlinux
        $(Q)$(MAKE) $(build)=$(boot)MACHINE=$(MACHINE) $(boot)/$@  --1
    @$(kecho) ' Kernel: $(boot)/$@ is ready'
    这里的vmlinux是编译生成的linux内核的elf文件:
    #file vmlinux
    vmlinux: ELF 32-bitLSB executable, ARM, version 1 (SYSV), statically linked, not stripped
    其中,(build)=$(boot)被扩展为了scripts/Makefile.build obj=arch/arm/boot
    buildscripts/Kbuild.include中定义的变量:
    build := -f$(srctree)/scripts/Makefile.build obj
    boot := arch/arm/boot 直接指明该架构的boot文件生成路径,而MACHINE则是由用户配置来决定,嵌入式物联网更多资料企鹅意义气呜呜吧久零就易,毕竟一个ARM CPU可以和各类外设组成不同的机器架构。
    ifneq ($(machine-y),)
    MACHINE  := arch/arm/mach-$(word 1,$(machine-y))/
    else
    MACHINE  :=
    endif
    比如:
    machine-$(CONFIG_ARCH_S3C64XX)    := s3c6400 s3c6410
    在内核配置文件.config可以找到CONFIG_ARCH_S3C64XX=y
    这样,语句(1)就可以解析成:
    make -fscripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/mach-s3c6400/arch/arm/boot/zImage
    接着看scripts/Makefile.build,它包含arch/arm/boot/Makefile文件的方式有些特殊,它是从上面的命令行得到obj,然后找到对应文件夹下的Makefile并执行。
    scripts/Makefile.build的开头,src的值被赋值为arch/arm/boot
    src := $(obj)
    … …
    # The filename Kbuildhas precedence over Makefile
    kbuild-dir := $(if$(filter /%,$(src)),$(src),$(srctree)/$(src))
    kbuild-file := $(if$(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
    include$(kbuild-file)
    kbuild-file就是src指定路径下的Makefile文件,此时就是arch/arm/boot/Makefile,它包含了构建arch/arm/boot/zImage的规则。
    PHONY := __build
    … …
    __build: $(if$(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
    KBUILD_BUILTIN 在顶层Makefile 中被初始化为1,所以这个规则的依赖需要一个builtin-target 变量。
    这个变量在scripts/Makefile.build中定义。
    ifneq ($(strip$(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
    builtin-target := $(obj)/built-in.o
    endif
    变量obj 就是vmlinux-dirs 变量指定的目录。所以这里会构建$(vmlinux-dirs)/built-in.o 目标,在scripts/Makefile.build文件中有这个目标的规则及命令的定义:
    # If the list ofobjects to link is empty, just create an empty built-in.o
    cmd_link_o_target =$(if $(strip $(obj-y)),\
                          $(cmd_make_builtin) $@$(filter $(obj-y), $^) \
                          $(cmd_secanalysis),\
                          $(cmd_make_empty_builtin)$@)
    $(builtin-target)(obj-y) FORCE
            $(call if_changed,link_o_target)
    vmlinux-dirs将在后面解释,它包含了所有由变量$(xx)代表的需要编译处理的文件夹。所有的目标文件生成规则在scripts/Makefile.build中定义如下:
    # Built-in andcomposite module parts
    $(obj)/%.o(src)/%.c $(recordmcount_source) $(objtool_obj) FORCE
            $(call cmd,force_checksrc)
            $(call if_changed_rule,cc_o_c)
    vmlinux在生成完毕后,接着会执行make -fscripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/mach-s3c6400/arch/arm/boot/zImagearch/arm/boot/Makefile中定义了如下规则:
    $(obj)/zImage:  $(obj)/compressed/vmlinux FORCE
            $(call if_changed,objcopy)
    变量obj的值即是arch/arm/boot。显然zImage此时又依赖于$(obj)/compressed/vmlinux
    $(obj)/compressed/vmlinux(obj)/Image FORCE
            $(Q)$(MAKE) $(build)=$(obj)/compressed$@
    扩展开的命令如下:
    make -f scripts/Makefile.buildobj=arch/arm/boot/compressed
    arch/arm/boot/compressed/vmlinux
    继续回到压缩vmlinux生成命令,make -f scripts/Makefile.build obj=arch/arm/boot/compressed arch/arm/boot/compressed/vmlinux。
    此时obj=arch/arm/boot/compressed,所以scripts/Makefile.build会自动包含arch/arm/boot/compressed/Makefile,该文件指明了arch/arm/boot/compressed/vmlinux的生成规则。
    arch/arm/boot/compressed/Makefile:
    $(obj)/vmlinux(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
                    $(addprefix $(obj)/, $(OBJS))$(lib1funcs) $(ashldi3) \
                     $(bswapsdi2) $(efi-obj-y) FORCE
            @$(check_for_multiple_zreladdr)
           $(call if_changed,ld)
            @$(check_for_bad_syms)
    这两个规则的第一个就是把由vmlinux 进行objcopy生成的Image进行压缩生成piggy.gz,然后生成piggy.ocmd_ld 命令在scripts/Makefile.lib 文件定义:
    quiet_cmd_ld =LD      $@
    cmd_ld = $(LD)$(LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) \
                  $(filter-out FORCE,$^) -o $@

    这里根据链接脚本arch/arm/boot/compressed/vmlinux.lds 链接生成了arch/arm/boot/compressed/vmlinux文件。然后在arch/arm/boot/Makefile规则中:
    $(obj)/zImage(obj)/compressed/vmlinux FORCE
    $(callif_changed,objcopy)
    这样,经过objcopy处理后便生成了最终的zImage

    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-5-1 01:11 , Processed in 0.120034 second(s), 15 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.