微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Arm Linux Kernel 构建 情景分析

Arm Linux Kernel 构建 情景分析

时间:11-09 来源:互联网 点击:

  • inux 的构建过程
  • arch/arm/boot/compressed/vmlinux 的构建过程
  • 源码是如何选择性地参与内核的构建的
之所以要分析 vmlinux 和 arch/arm/boot/compressed/vmlinux ,是因为这个两个文件是最原始的两个可执行文件:Image 由 vmlinux 生成;zImage 由 arch/arm/boot/compressed/vmlinux 生成。分析这连个文件的生成,还有助于分析 linux 内核的启动过程。

基础

vmlinux 是 makefile 中的一个目标。makefile 中的规则定义了目标和源码的关系,命令则定义了如何由源码生成目标,变量起辅助作用。规则、命令和变量是 makefile 的三大要素。理清 makefile 规则中定义的依赖关系是分析构建过程的关键。涉及到的几个重要文件:

Makefilearch/arm/Makefilearch/arm/boot/Makefilearch/arm/mach-msm/Makefile.bootarch/arm/compressed/Makefile

vmlinux 是一个可执行程序,其链接过程必然涉及的链接脚本,链接脚本是做什么的?看看 ld 手册中的描述:

通过 lds 文件,我们至少可以知道一个可执行程序的入口在哪里。

这里又要涉及到几个重要文件:

# 对应 vmlinuxarch/arm/kernel/vmlinux.lds# 对应 /arch/arm/boot/compressed/vmlinuxarch/arm/boot/compressed/vmlinux.lds

vmlinux 是一个可执行程序,由源码编译、链接而来。那么是哪些源码参与了构建过程,又是如何控制这些源码参与的?后面会分析。

为了分析 makefile,这里借用了 UML 的概念。

用 包 表示 makefile 文件;用 类 表示 目标和文件;用类间依赖表示目标的依赖;用组合表示变量的定义。

下面是一个总图,表明了各个目标之间的依赖关系:

(红色边框是可执行程序,蓝色边框是对应的链接脚本)

vmlinux 的构建过程

和 lds 文件的关系

?依赖链:

_all->all->vmlinux->$(vmlinux-lds)=arch/arm/kernel/vmlinux.lds

从 _all 到 all:

PHONY += allifeq ($(KBUILD_EXTMOD),)_all: allelse_all: modulesendif

KBUILD_EXTMOD 只有在内核树外编译内核模块的时候才会定义 M 变量,从而给其赋值,否则为空,这里为空。

从 all 到 vmlinux:

all: vmlinux

从 vmlinux 到 $(vmlinux-lds):

vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE

$(vmlinux-lds) 定义:

vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds

和源码的关系

?依赖链:

_all->all->vmlinux->$(vmlinux-init)+$(vmlinux-main)

看看这个:

# vmlinux# ^# # +-< $(vmlinux-init)#  +--< init/version.o + more# # +--< $(vmlinux-main)#  +--< driver/built-in.o mm/built-in.o + more# # +-< kallsyms.o (see description in CONFIG_KALLSYMS section)

关键部分上面已经列出,这里再次列出来:

vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE

那么 $(vmlinux-init) 连个变量是什么呢?通过分析,第一次展开后为:“$(head-y) $(init-y)”。没有找到 $(head-y),而 $(init-y) 最终展开为:init/built-in.o。

到这里有点眉目了(回头看看 make 过程输出的信息,里面有大量的 built-in.o)。可以说是众多的 built-in.o构成了vmlinux。所以 vmlinux 和源码的关系转变成了 built-in.o 和源码的关系。

还是看 make 的输出信息:

CC init/version.oCC init/do_mounts.oCC init/do_mounts_rd.oCC init/do_mounts_initrd.oLD init/mounts.oCC init/initramfs.oCC init/calibrate.oLD init/built-in.o

可以推测:init/built-in.o 是由 init 目录下的 源码编译、链接而成。在 init 目录下发现 Makefile:

obj-y := main.o version.o mounts.oifneq ($(CONFIG_BLK_DEV_INITRD),y)obj-y += noinitramfs.oelseobj-$(CONFIG_BLK_DEV_INITRD)+= initramfs.oendifobj-$(CONFIG_GENERIC_CALIBRATE_DELAY)+= calibrate.omounts-y := do_mounts.omounts-$(CONFIG_BLK_DEV_RAM)+= do_mounts_rd.omounts-$(CONFIG_BLK_DEV_INITRD)+= do_mounts_initrd.omounts-$(CONFIG_BLK_DEV_MD)+= do_mounts_md.o

有内核开发经验的开发者应该知道,赋值到 obj-y 的目标会被编译进 vmlinux,至于是如何控制的,推测 kbuild 系统是有参与的,这属于 make 和 kubild 的内部原理,这里不分析了,知道有这么回事,会用就行了。$(CONFIG_BLK_DEV_INITRD) 等变量在 .config(没错,就是保存内核配置的文件) 文件中定义:

CONFIG_RELAY=yCONFIG_BLK_DEV_INITRD=yCONFIG_INITRAMFS_SOURCE=""
这里 vmlinux 和源码的关系就

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top