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启动流程以及编译流程分析的主要内容,如果未能解决你的问题,请参考以下文章

BSP开发之kernelLinux启动流程以及编译流程分析

BSP开发之ubootuboot常用命令以及代码分析

BSP开发之ubootuboot常用命令以及代码分析

Hi3516开发笔记:Hi3516虚拟机基础环境搭建之交叉编译环境境搭建以及开机启动脚本分析

Synergy 入口函数启动流程

Hi3516开发笔记:Hi3516虚拟机基础环境搭建之交叉编译环境境搭建以及开机启动脚本分析