1 kernel编译初体验
编译内核之前需要先在 ubuntu 上安装 lzop 库:
sudo apt-get install lzop
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
这里选择的是imx_v7_defconfig:
scripts/kconfig/conf --defconfig=arch/arm/configs/imx_v7_defconfig Kconfig
Linux 的图行界面配置和 uboot 是一样的,这里我们不需要做任何的配置,直接按两下 ESC键退出,退出图形界面以后会自动开始编译Linux:
编译完成后如下图:
先编译出zimage,各种dtb,最后编译出ko。
2 kernel源码目录结构分析
linux内核源码编译后目录结构如下:
架构 | 描述 |
---|---|
arch | 架构相关目录 |
block | 块设备相关目录 |
crypto | 加密相关目录 |
Documentation | 文档相关目录 |
drivers | 驱动相关目录 |
firmeare | 固件相关目录 |
fs | 文件系统相关目录 |
include | 头文件相关目录 |
init | 初始化相关目录 |
ipc | 进程间通信相关目录 |
kernel | 内核相关目录 |
lib | 库相关目录 |
mm | 内存管理相关目录 |
net | 网络相关目录 |
samples | 例程相关目录 |
scripts | 脚本相关目录 |
security | 安全相关目录 |
sound | 音频处理相关目录 |
tools | 工具相关目录 |
usr | 与 initramfs 相关的目录,用于生成initramfs |
virt | 提供虚拟机技术(KVM) |
.gitignore | git 工具相关文件 |
.mailmap | 邮件列表 |
COPYING | 版权声明 |
CREDITS | Linux 贡献者 |
Kbuild | Makefile 会读取此文件 |
Kconfig | 图形化配置界面的配置文件 |
MAINTAINERS | 维护者名单 |
Makefile | Linux 顶层 Makefile |
编译产生的文件如下:
架构 | 描述 |
---|---|
.config | Linux 最终使用的配置文件 |
.version | 好像和版本有关 |
.vmlinux.cmd | cmd 文件,用于链接生成 vmlinux |
Module.xx、modules.xx | 一系列文件,和模块有关 |
System.map | 符号表 |
vmlinux | 编译出来的、未压缩的 ELF 格式Linux 文件 |
vmlinux.o | 编译出来的 vmlinux.o 文件 |
2.1 arch 目录
和架构有关的目录,比如 arm、arm64、avr32、x86 等等架构。每种架构都对应一个目录,在这些目录中又有很多子目录,比如 boot、common、configs 等等,以 arch/arm 为例:
这些子目录用于控制系统引导、系统调用、动态调频、主频设置等。
2.1.1 arch/arm/configs
arch/arm/configs 目录是不同平台的默认配置文件:xxx_defconfig:
I.MX6U-ALPHA 开发板的默认配置文件:arch/arm/configs/imx_v7_defconfig
2.1.2 arch/arm/boot/dts
arch/arm/boot/dts 目录里面是对应开发平台的设备树文件, I.MX6U-ALPHA 开发板对应的设备树文件如下:
2.1.3 arch/arm/boot
会保存编译出来的 Image 和 zImage 镜像文件,而 zImage 就是我们要用的 linux 镜像文件。
2.1.4 arch/arm/mach-xxx
相应平台的驱动和初始化文件,比如 mach-imx 目录里面就是 I.MX 系列 CPU 的驱动和初始化文件。
2.2 block 目录
块设备目录,像 SD 卡、EMMC、NAND、硬盘等存储设备就属于块设备,block 目录中存放着管理块设备的相关文件。
2.3 crypto 目录
存放加密算法,比如常见的 crc、crc32、md4、md5、hash 等加密算法。
2.4 Documentation 目录
2.5 drivers 目录
驱动目录文件,此目录根据驱动类型的不同,分门别类进行整理,比如 drivers/i2c 就是 I2C相关驱动目录,drivers/gpio 就是 GPIO 相关的驱动目录。
2.6 firmware 目录
此目录用于存放固件。
2.7 fs 目录
存放文件系统,比如 fs/ext2、fs/ext4、fs/f2fs 等,分别是 ext2、ext4 和 f2fs 等文件系统。
2.8 init 目录
此目录存放 Linux 内核启动的时候初始化代码。
2.9 ipc 目录
IPC 为进程间通信,ipc 目录是进程间通信的具体实现代码。
3 VSCode 工程创建
分析 Linux 的顶层 Makefile 之前,先创建 VSCode 工程,新建文件.vscode/settings.json:
.vscode/settings.json
{
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.o":true,
"**/*.su":true,
"**/*.cmd":true,
"Documentation":true,
/* 屏蔽不用的架构相关的文件 */
"arch/alpha":true,
"arch/arc":true,
"arch/arm64":true,
"arch/avr32":true,
"arch/[b-z]*":true,
"arch/arm/plat*":true,
"arch/arm/mach-[a-h]*":true,
"arch/arm/mach-[n-z]*":true,
"arch/arm/mach-i[n-z]*":true,
"arch/arm/mach-m[e-v]*":true,
"arch/arm/mach-k*":true,
"arch/arm/mach-l*":true,
/* 屏蔽排除不用的配置文件 */
"arch/arm/configs/[a-h]*":true,
"arch/arm/configs/[j-z]*":true,
"arch/arm/configs/imo*":true,
"arch/arm/configs/in*":true,
"arch/arm/configs/io*":true,
"arch/arm/configs/ix*":true,
/* 屏蔽掉不用的 DTB 文件 */
"arch/arm/boot/dts/[a-h]*":true,
"arch/arm/boot/dts/[k-z]*":true,
"arch/arm/boot/dts/in*":true,
"arch/arm/boot/dts/imx1*":true,
"arch/arm/boot/dts/imx7*":true,
"arch/arm/boot/dts/imx2*":true,
"arch/arm/boot/dts/imx3*":true,
"arch/arm/boot/dts/imx5*":true,
"arch/arm/boot/dts/imx6d*":true,
"arch/arm/boot/dts/imx6q*":true,
"arch/arm/boot/dts/imx6s*":true,
"arch/arm/boot/dts/imx6ul-*":true,
"arch/arm/boot/dts/imx6ull-9x9*":true,
"arch/arm/boot/dts/imx6ull-14x14-ddr*":true,
},
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/*.o":true,
"**/*.su":true,
"**/*.cmd":true,
"Documentation":true,
/* 屏蔽不用的架构相关的文件 */
"arch/alpha":true,
"arch/arc":true,
"arch/arm64":true,
"arch/avr32":true,
"arch/[b-z]*":true,
"arch/arm/plat*":true,
"arch/arm/mach-[a-h]*":true,
"arch/arm/mach-[n-z]*":true,
"arch/arm/mach-i[n-z]*":true,
"arch/arm/mach-m[e-v]*":true,
"arch/arm/mach-k*":true,
"arch/arm/mach-l*":true,
/* 屏蔽排除不用的配置文件 */
"arch/arm/configs/[a-h]*":true,
"arch/arm/configs/[j-z]*":true,
"arch/arm/configs/imo*":true,
"arch/arm/configs/in*":true,
"arch/arm/configs/io*":true,
"arch/arm/configs/ix*":true,
/* 屏蔽掉不用的 DTB 文件 */
"arch/arm/boot/dts/[a-h]*":true,
"arch/arm/boot/dts/[k-z]*":true,
"arch/arm/boot/dts/in*":true,
"arch/arm/boot/dts/imx1*":true,
"arch/arm/boot/dts/imx7*":true,
"arch/arm/boot/dts/imx2*":true,
"arch/arm/boot/dts/imx3*":true,
"arch/arm/boot/dts/imx5*":true,
"arch/arm/boot/dts/imx6d*":true,
"arch/arm/boot/dts/imx6q*":true,
"arch/arm/boot/dts/imx6s*":true,
"arch/arm/boot/dts/imx6ul-*":true,
"arch/arm/boot/dts/imx6ull-9x9*":true,
"arch/arm/boot/dts/imx6ull-14x14-ddr*":true,
}
}
方便排除一些不必要的文件和搜索路径,方便加速搜索速率。
4 linux顶层 Makefile分析
Linux 的顶层 Makefile 和 uboot 的顶层 Makefile 非常相似。
Uboot顶层Makefile解析-1. defconfig过程分析
uboot顶层makefile-2编译过程
4.1 版本号
1 VERSION = 4
2 PATCHLEVEL = 1
3 SUBLEVEL = 15
4 EXTRAVERSION =
4.2 MAKEFLAGS 变量
16 MAKEFLAGS += -rR --include-dir=$(CURDIR)
4.3 命令输出详细程度
和uboot完全一样。make -s设置成静默输出,将会silent_输出,不打印任何提示信息。如下:
4.4 设置编译结果输出目录
和uboot完全一样。Uboot顶层Makefile解析-1. defconfig过程分析
4.5 代码检查
和uboot完全一样。Uboot顶层Makefile解析-1. defconfig过程分析
4.6 子模块编译
和uboot完全一样。Uboot顶层Makefile解析-1. defconfig过程分析
4.7 设置目标架构和交叉编译器
和uboot完全一样。Uboot顶层Makefile解析-1. defconfig过程分析
4.8 调用 scripts/Kbuild.include
和uboot完全一样。Uboot顶层Makefile解析-1. defconfig过程分析
4.9 头文件路径变量
顶层 Makefile 定义了两个变量保存头文件路径:USERINCLUDE 和 LINUXINCLUDE:
其中srctree=.,hdr-arch=arm,KBUILD_SRC 为空,因此,将 USERINCLUDE 和 LINUXINCLUDE 展
开以后为:
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
4.10 核心变量导出
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_KASAN
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
5 linux内核defconfig过程
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig
5.1 配置变量
同uboot一样,Uboot顶层Makefile解析-1. defconfig过程分析 得到:
config-targets= 1
mixed-targets= 0
dot-config= 1
5.2 执行3个依赖
继续看顶层makefile, 同uboot一样,Uboot顶层Makefile解析-1. defconfig过程分析, 三个依赖为scripts_basic,outputmakefile,FORCE。
build 定义在文件 scripts/Kbuild.include 中,值为:
build := -f $(srctree)/scripts/Makefile.build obj
5.2.1 scripts_basic
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
scripts_basic展开后:
scripts_basic:
@make -f ./scripts/Makefile.build obj=scripts/basic //也可以没有@,视配置而定
@rm -f . tmp_quiet_recordmcount //也可以没有
从scripts/Makefile.build开始编译默认目标_build。scripts_basic就是利用scripts/Makefile.build去找到_build目标,然后去scripts/basic目录编译出fixdep。
5.2.1.1 scripts/Makefile.build分析
scripts/Makefile.build分析详见Uboot顶层Makefile解析-1. defconfig过程分析 第12.3.1.1 scripts/Makefile.build。
最后展开:
kbuild-dir=./scripts/basic
kbuild-file= ./scripts/basic/Makefile
继续分析 scripts/Makefile.build, 命令“@make -f ./scripts/Makefile.build obj=scripts/basic”没有指定目标,所以会使用到默认目标__build
在顶层 Makefile 中,KBUILD_BUILTIN 为 1,KBUILD_MODULES 为空,因此展开后目标__build 为:
__build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
@:
打印出依赖:
builtin-target =
lib-target =
extra-y =
subdir-ym =
always = scripts/basic/fixdep scripts/basic/bin2c
只有 always 有效,因此__build 最终为:
__build: scripts/basic/fixdep scripts/basic/bin2c
@:
综上所述,scripts_basic 目标的作用就是编译出 scripts/basic/fixdep 和 scripts/basic/bin2c 这两个软件。
5.2.2 outputmakefile:
由于KBUILD_SRC为空,不执行。否则会为源码路径创建source这个符号链接,执行mkmakefile。
5.2.3 FORCE:
Makefile最底下定了FORCE目标,可以看到什么都不执行。
5.3 产生.config
回到顶层Makefile的%config 处,三个依赖执行完后继续执行,展开:
make -f ./scripts/Makefile.build obj=scripts/kconfig imx_v7_defconfig
5.3.1 继续scripts/Makefile.build分析
前面整理了scripts/Makefile.build用到的变量include内容:
src= scripts/kconfig
kbuild-dir = ./scripts/kconfig
kbuild-file = ./scripts/kconfig/Makefile
include ./scripts/kconfig/Makefile
可以看出,scripts/Makefile.build会读取 scripts/kconfig/Makefile 中的内容:
113 %_defconfig: $(obj)/conf
114 $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
目标%_defconfig 与 xxx_defconfig 匹配,所以会执行这条规则,将其展开就是:
%_defconfig: scripts/kconfig/conf
@ scripts/kconfig/conf --defconfig=arch/arm/configs/%_defconfig Kconfig
%_defconfig依赖scripts/kconfig/conf,所以会编译scripts/kconfig/conf.c生成conf 这个软件。此软件就会将%_defconfig 中的配置输出到.config 文件中,最终生成 Linux kernel 根目录下的.config 文件。
标签:true,scripts,Makefile,内核,linux,arch,arm,boot From: https://www.cnblogs.com/fuzidage/p/17984739