BSP开发之kernelLinux启动流程以及编译流程分析
Posted 与光同程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BSP开发之kernelLinux启动流程以及编译流程分析相关的知识,希望对你有一定的参考价值。
文章目录
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
字节的“头”,这个头信息描述了该镜像文件的类型、加载位置、生成时间、大小等信息
内核启动流程分析
以上是关于BSP开发之kernelLinux启动流程以及编译流程分析的主要内容,如果未能解决你的问题,请参考以下文章