【BSP开发之kernel】Linux启动流程以及编译流程分析

linux 顶层Makefile分析

MAKEFLAGS += -rR

# 静默输出 make V=1 静默输出
ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

# 设置编译结果输出目录 make O=path
ifeq ("$(origin O)", "command line")
  KBUILD_OUTPUT := $(O)
endif

# 默认编译目标
PHONY := _all
_all:

# 代码检查 make C=1 使能带代码检查
# make C=2 检查所有的源码文件
ifeq ("$(origin C)", "command line")
  KBUILD_CHECKSRC = $(C)
endif
ifndef KBUILD_CHECKSRC
  KBUILD_CHECKSRC = 0
endif

ifdef SUBDIRS
  KBUILD_EXTMOD ?= $(SUBDIRS)
endif

ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif

PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif

ifeq ($(KBUILD_SRC),)
        # building in the source tree
        srctree := .
else
        ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR)))
                # building in a subdirectory of the source tree
                srctree := ..
        else
                srctree := $(KBUILD_SRC)
        endif
endif
objtree		:= .
src		:= $(srctree)
obj		:= $(objtree)

VPATH		:= $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))

export srctree objtree VPATH

# 设置架构以及交叉编译器
ARCH		= arm
CROSS_COMPILE	=arm-linux-gnueabi-


KCONFIG_CONFIG	?= .config
export KCONFIG_CONFIG

# SHELL used by kbuild
# CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
# 	  else if [ -x /bin/bash ]; then echo /bin/bash; \
# 	  else echo sh; fi ; fi)
AS		= $(CROSS_COMPILE)as
LD		= $(CROSS_COMPILE)ld
CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nm
STRIP		= $(CROSS_COMPILE)strip
OBJCOPY		= $(CROSS_COMPILE)objcopy
OBJDUMP		= $(CROSS_COMPILE)objdump
AWK		= awk
GENKSYMS	= scripts/genksyms/genksyms
INSTALLKERNEL  := installkernel
DEPMOD		= /sbin/depmod
PERL		= perl
PYTHON		= python
CHECK		= sparse

CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
		  -Wbitwise -Wno-return-void $(CF)
CFLAGS_MODULE   =
AFLAGS_MODULE   =
LDFLAGS_MODULE  =
CFLAGS_KERNEL	=
AFLAGS_KERNEL	=
CFLAGS_GCOV	= -fprofile-arcs -ftest-coverage


# 添加头文件目录
USERINCLUDE    := \
		-I$(srctree)/arch/$(hdr-arch)/include/uapi \
		-Iarch/$(hdr-arch)/include/generated/uapi \
		-I$(srctree)/include/uapi \
		-Iinclude/generated/uapi \
                -include $(srctree)/include/linux/kconfig.h
LINUXINCLUDE    := \
		-I$(srctree)/arch/$(hdr-arch)/include \
		-Iarch/$(hdr-arch)/include/generated/uapi \
		-Iarch/$(hdr-arch)/include/generated \
		$(if $(KBUILD_SRC), -I$(srctree)/include) \
		-Iinclude \
		$(USERINCLUDE)

# make xxx_deconfig 配置过程
config-targets := 0
mixed-targets  := 0
dot-config     := 1
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
	ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
		dot-config := 0
	endif
endif
ifeq ($(KBUILD_EXTMOD),)
        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
                config-targets := 1
                ifneq ($(words $(MAKECMDGOALS)),1)
                        mixed-targets := 1
                endif
        endif
endif

ifeq ($(mixed-targets),1)
PHONY += $(MAKECMDGOALS) __build_one_by_one
$(filter-out __build_one_by_one, $(MAKECMDGOALS)): __build_one_by_one
	@:
__build_one_by_one:
	$(Q)set -e; \
	for i in $(MAKECMDGOALS); do \
		$(MAKE) -f $(srctree)/Makefile $$i; \
	done
else
ifeq ($(config-targets),1)

include $(srctree)/arch/$(SRCARCH)/Makefile
export KBUILD_DEFCONFIG KBUILD_KCONFIG

config: scripts_basic outputmakefile FORCE
	$(Q)$(MAKE) $(build)=scripts/kconfig $@

%config: scripts_basic outputmakefile FORCE
	$(Q)$(MAKE) $(build)=scripts/kconfig $@
else
ifeq ($(KBUILD_EXTMOD),)
PHONY += scripts
scripts: scripts_basic include/config/auto.conf include/config/tristate.conf \
	 asm-generic
	$(Q)$(MAKE) $(build)=$(@)
init-y		:= init/
drivers-y	:= drivers/ sound/ firmware/
net-y		:= net/
libs-y		:= lib/
core-y		:= usr/
endif # KBUILD_EXTMOD

ifeq ($(dot-config),1)
ifeq ($(KBUILD_EXTMOD),)
-include include/config/auto.conf.cmd

$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
else
PHONY += include/config/auto.conf
include/config/auto.conf:
	$(Q)test -e include/generated/autoconf.h -a -e $@ || (		\
	echo >&2;							\
	echo >&2 "  ERROR: Kernel configuration is invalid.";		\
	echo >&2 "         include/generated/autoconf.h or $@ are missing.";\
	echo >&2 "         Run 'make oldconfig && make prepare' on kernel src to fix it.";	\
	echo >&2 ;							\
	/bin/false)
endif # KBUILD_EXTMOD

else
include/config/auto.conf: ;
endif # $(dot-config)
all: vmlinux

make 过程分析

_all-->all-->vmlinux-->scripts/link-vmlinux.sh 
                       head-y  arch/arm/kernel/head.o
                       init -y init/built-in.o
                       libs-y  libs-y = arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o
                       drivers-y = drivers/built-in.o sound/built-in.o firmware/built-in.o
                       net-y   snet/built-in.o
                       core-y   usr kernel fs ipc security crypto block
                            usr/built-in.o arch/arm/vfp/built-in.o \
                            arch/arm/vdso/built-in.o arch/arm/kernel/built-in.o \
                            arch/arm/mm/built-in.o arch/arm/common/built-in.o \
                            arch/arm/probes/built-in.o arch/arm/net/built-in.o \
                            arch/arm/crypto/built-in.o arch/arm/firmware/built-in.o \
                            arch/arm/mach-imx/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/kernel/vmlinux.lds 就是整个 Linux 的链接脚本。

最终 vmlinux 依赖于以下文件:

vmlinux-deps = arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o \
init/built-in.o usr/built-in.o \
arch/arm/vfp/built-in.o arch/arm/vdso/built-in.o \
arch/arm/kernel/built-in.o arch/arm/mm/built-in.o \
arch/arm/common/built-in.o arch/arm/probes/built-in.o \
arch/arm/net/built-in.o arch/arm/crypto/built-in.o \
arch/arm/firmware/built-in.o arch/arm/mach-imx/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

子文件夹编译

vmlinux-dirs = init usr arch/arm/vfp \
arch/arm/vdso arch/arm/kernel arch/arm/mm \
arch/arm/common arch/arm/probes arch/arm/net \
arch/arm/crypto arch/arm/firmware arch/arm/mach-imx\
kernel mm fs \
ipc security crypto \
block drivers sound \
firmware net arch/arm/lib \
lib
$(vmlinux-dirs): prepare scripts
    $(Q)$(MAKE) $(build)=$@

展开就是 @ make -f ./scripts/Makefile.build obj=$@
以 init 为例子目录编译脚本为:
@ make -f ./scripts/Makefile.build obj=init

Makefile.build 编译出子文件 build-in.o 过程分析

_build–>: $(builtin-target)
$(lib-target)
$(extra-y)
$(subdir-ym)
$(always)

$(builtin-target): $(obj-y) FORCE
$(call if_changed,link_o_target) -->= $(obj)/built-in.o

vmlinux、Image,zImage、uImage 的区别

vmlinux 是编译出来的最原始的内核文件,是未压缩的
Image 是 Linux 内核镜像文件,但是 Image 仅包含可执行的二进制数据。Image 就是使

用 objcopy 取消掉 vmlinux 中的一些其他信息
zImage 是经过 gzip 压缩后的 Image
uImage 是老版本 uboot 专用的镜像文件,uImag 是在 zImage 前面加了一个长度为 64
字节的“头”,这个头信息描述了该镜像文件的类型、加载位置、生成时间、大小等信息

内核启动流程分析

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

与光同程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值