ZYNQ 7020内核kernel源码解析

**

Xilinx ZYNQ 7020 ARM 内核kernel源码解析

**
还记得2018年的时候,kernel还是4.9.0 ,到了2022变成了5.15了,三年疫情过去了,我们的技术一直在精进。国产加油,中国加油。无论如何变,它还是LINUX内核,你要了解了,什么版本都一样,一通百通。你要是不懂这些知识,就等着主管K你吧,这是你应该受的。
上链接:https://gitcode.net/mirrors/xilinx/linux-xlnx
此文档,还是以4.9.0来讲解,大家可以下载到这个版本。还是那句话:你强就不用petalinux.

Kernel 顶层 Makefile
之前分析过 uboot 源码目录下的顶层 makefile 文件,uboot 的顶层 makefile 参考了了许多 linux 顶层 makefile 的代码,前面有很多代码思路基本差不多

一、版本号

VERSION = 4
PATCHLEVEL = 9
SUBLEVEL = 0
EXTRAVERSION =
NAME = Roaring Lionus

二、MAKEFLAGS 变量

MAKEFLAGS用来查找相对于内核 src 根目录的 make include 文件,他的值 始终自动的传递给子 make,我们可以在代码中看到 MAKEFLAGS:
MAKEFLAGS += -rR --include-dir=$(CURDIR)
MAKEFLAGS += --no-print-directory
Clear a bunch of variables before executing the submake

tools/: FORCE
$(Q)mkdir -p $(objtree)/tools
( Q ) (Q) (Q)(MAKE) LDFLAGS= MAKEFLAGS=“ ( f i l t e r − − j (filter --j% -j, (filterj(MAKEFLAGS))” O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/
tools/%: FORCE
$(Q)mkdir -p $(objtree)/tools
( Q ) (Q) (Q)(MAKE) LDFLAGS= MAKEFLAGS=“ ( f i l t e r − − j (filter --j% -j, (filterj(MAKEFLAGS))” O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/ $*

三、命令输出

Linux 编译的时候可以通过 “V=1” 来输出完整的命令,和 uboot 一样

Use ‘make V=1’ to see the full commands

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

If the user is running make -s (silent mode), suppress echoing of # commands

ifneq ( ( f i l t e r 4. (filter 4.%, (filter4.(MAKE_VERSION)),) # make-4
ifneq ( ( f i l t e r (filter %s , (filter(firstword xKaTeX parse error: Expected 'EOF', got '#' at position 48: …endif else #̲ make-3.8x ifne…(filter s% -s%,$(MAKEFLAGS)),)
quiet=silent_
endif
endif
export quiet Q KBUILD_VERBOSE

V 为 1, quiet 和 Q 为空,输出完整命令,V 为 0 ,则 quiet=quiet_、Q = @,屏蔽掉完整命令

四、静默输出

编译的时候使用 “make -s” 就可实现静默编译,编译的时候就不会打印任何的信息:

If the user is running make -s (silent mode), suppress echoing of # commands

ifneq ( ( f i l t e r 4. (filter 4.%, (filter4.(MAKE_VERSION)),) # make-4
ifneq ( ( f i l t e r (filter %s , (filter(firstword xKaTeX parse error: Expected 'EOF', got '#' at position 48: …endif else #̲ make-3.8x ifne…(filter s% -s%,$(MAKEFLAGS)),)
quiet=silent_
endif
endif
quiet 为 silent_ 时不会打印任何信息
后面还有一行
export quiet Q KBUILD_VERBOSE用来传递参数给子 make

五、编译结果输出目录

编译时使用 “O=xxx” 可将编译产生的过程文件输出到指定的目录中
ifeq ($(KBUILD_SRC),)

OK, Make called in directory where kernel src resides # Do we want to locate output files in a separate directory?

ifeq (“$(origin O)”, “command line”)
KBUILD_OUTPUT := $(O)
endif

That’s our default target when none is given on the command line

PHONY := _all
_all:

Cancel implicit rules on top Makefile

$(CURDIR)/Makefile Makefile: ;

代码判断 O 存在且来自命令行后就会将 O 的值赋值给 KBUILD_OUTPUT (编译输出目录),然后判断 KBUILD_OUTPUT 不为空的话,则创建该目录,并将所有的 make 结果设置为该目录
ifneq ($(KBUILD_OUTPUT),)

Invoke a second make in the output directory, passing relevant variables

check that the output directory actually exists

saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT)
&& /bin/pwd)
$(if $(KBUILD_OUTPUT),
( e r r o r f a i l e d t o c r e a t e o u t p u t d i r e c t o r y " (error failed to create output directory " (errorfailedtocreateoutputdirectory"(saved-output)"))

PHONY += $(MAKECMDGOALS) sub-make

$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
@:

sub-make:
( Q ) (Q) (Q)(MAKE) -C ( K B U I L D O U T P U T ) K B U I L D S R C = (KBUILD_OUTPUT) KBUILD_SRC= (KBUILDOUTPUT)KBUILDSRC=(CURDIR)
-f $(CURDIR)/Makefile ( f i l t e r − o u t a l l s u b − m a k e , (filter-out _all sub-make, (filteroutallsubmake,(MAKECMDGOALS))

Leave processing to above invocation of make

skip-makefile := 1
endif # ifneq (KaTeX parse error: Expected 'EOF', got '#' at position 25: …UTPUT),) endif #̲ ifeq ((KBUILD_SRC),)

六、代码检查

使用参数 “ C=1” 使能代码检查,检查那些需要重新编译的文件,“C=2”用于检查所有的源码文件
ifeq (“$(origin C)”, “command line”)
KBUILD_CHECKSRC = $©
endif
ifndef KBUILD_CHECKSRC
KBUILD_CHECKSRC = 0
endif

#lai add it//希望我的姓可以明扬天下。为中国1亿技术人加油。
first_a = $(CXX)
second_a = g++
ifeq (first_a, second_a)
PHONY += all
Else
代码逻辑和前面的相同

七、模块编译

Linux 允许单独编译某个模块,使用命令 “make M=dir” 或者旧语法 “make SUBDIRS=dir”,相关代码如下:
if SUBDIRS
KBUILD_EXTMOD ?= $(SUBDIRS)
endifdef

ifeq (“$(origin M)”, “command line”)
KBUILD_EXTMOD := ( M ) e n d i f 代 码 对 a l l 和 M 两 个 指 令 都 支 持 P H O N Y + = a l l i f e q ( (M) endif 代码对all和M两个指令都支持 PHONY += all ifeq ( (M)endifallMPHONY+=allifeq((KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif

根据 KBUILD_EXTMOD 决定编译部分还是全部模块,然后设置 srctree、objtree、VPATH 这三个变量并输出

ifeq (KaTeX parse error: Expected 'EOF', got '#' at position 24: …SRC),) #̲ building in th…(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 := ( s r c t r e e ) (srctree) (srctree)(if ( K B U I L D E X T M O D ) , : (KBUILD_EXTMOD),: (KBUILDEXTMOD),:(KBUILD_EXTMOD))

八、设置目标架构和交叉编译器

Linux 编译要设置目标板架构 ARCH 和交叉编译器 CROSS_COMPILE

CROSS_COMPILE specify the prefix used for all executables used

during compilation. Only gcc and related bin-utils executables # are prefixed with $(CROSS_COMPILE). # CROSS_COMPILE can be set on the command line # make CROSS_COMPILE=ia64-linux- # Alternatively CROSS_COMPILE can be set in the environment. # A third alternative is to store a setting in .config so that plain # “make” in the configured kernel build directory always uses that. # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile

ARCH ?= $(SUBARCH)
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:“%”=%)

编译时要把这两个参数传进去.
我们在实际操作中,一般会如下:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zynq _defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8

九、调用构建文件

Linux 顶层 Makefile 也会调用文件 scripts/Kbuild.include,里面是一些辅助调用的代码:
scripts/Kbuild.include: ;
include scripts/Kbuild.include

十、交叉编译工具链设置

下面的代码是配置交叉编译工具的代码,比如 LD-链接器、gcc 编译器等等

Make variables (CC, etc…)

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)
NOSTDINC_FLAGS =
CFLAGS_MODULE =
AFLAGS_MODULE =
LDFLAGS_MODULE =
CFLAGS_KERNEL =
AFLAGS_KERNEL =
LDFLAGS_vmlinux =
CFLAGS_GCOV = -fprofile-arcs -ftest-coverage -fno-tree-loop-im -Wno-maybe-uninitialized
CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)

十一、头文件路径变量

顶层 Makefile 定义了两个变量 保存头文件路径:USERINCLUDE 和 LINUXINCLUDE

Use USERINCLUDE when you must reference the UAPI directories only.

USERINCLUDE :=
-I ( s r c t r e e ) / a r c h / (srctree)/arch/ (srctree)/arch/(hdr-arch)/include/uapi
-I ( o b j t r e e ) / a r c h / (objtree)/arch/ (objtree)/arch/(hdr-arch)/include/generated/uapi
-IKaTeX parse error: Undefined control sequence: \ at position 24: …)/include/uapi \̲ ̲ -I(objtree)/include/generated/uapi
-include $(srctree)/include/linux/kconfig.h

Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option

LINUXINCLUDE :=
-I ( s r c t r e e ) / a r c h / (srctree)/arch/ (srctree)/arch/(hdr-arch)/include
-I ( s r c t r e e ) / a r c h / (srctree)/arch/ (srctree)/arch/(hdr-arch)/mach-zynq
-I ( o b j t r e e ) / a r c h / (objtree)/arch/ (objtree)/arch/(hdr-arch)/include/generated/uapi
-I ( o b j t r e e ) / a r c h / (objtree)/arch/ (objtree)/arch/(hdr-arch)/include/generated
$(if ( K B U I L D S R C ) , − I (KBUILD_SRC), -I (KBUILDSRC),I(srctree)/include)
-I$(objtree)/include

LINUXINCLUDE += $(filter-out ( L I N U X I N C L U D E ) , (LINUXINCLUDE), (LINUXINCLUDE),(USERINCLUDE))
在默认输入情况下,srctree=.,hdr-arch=arm,KBUILD_SRC 为空,带入后展开代码:
USERINCLUDE :=
-I./arch/arm/include/uapi
-Iarch/arm/include/generated/uapi
-I./include/uapi
-Iinclude/generated/uapi
-include ./include/linux/kconfig.h
LINUXINCLUDE :=
-I./arch/arm/include
-Iarch/arm/include/generated/uapi
-Iarch/arm/include/generated
-Iinclude
-I./arch/arm/include/uapi
-Iarch/arm/include/generated/uapi
-I./include/uapi
-Iinclude/generated/uapi
-include ./include/linux/kconfig.h

十二、导出变量

后面就是一堆导出变量,用于给子 make 使用

export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP
export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS

export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV CFLAGS_KCOV CFLAGS_KASAN CFLAGS_UBSAN
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
export KBUILD_ARFLAGS

When compiling out-of-tree modules, put MODVERDIR in the module # tree rather than in the kernel tree. The kernel tree might # even be read-only.

export MODVERDIR := $(if ( K B U I L D E X T M O D ) , (KBUILD_EXTMOD), (KBUILDEXTMOD),(firstword $(KBUILD_EXTMOD))/).tmp_versions

Files to ignore in find … statements

export RCS_FIND_IGNORE := ( -name SCCS -o -name BitKeeper -o -name .svn -o
-name CVS -o -name .pc -o -name .hg -o -name .git )
-prune -o
export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn
–exclude CVS --exclude .pc --exclude .hg --exclude .git
(未完,待更新)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值