首页 > 系统相关 >linux内核-1.Linux 内核顶层 Makefile 详解

linux内核-1.Linux 内核顶层 Makefile 详解

时间:2024-01-25 14:45:13浏览次数:34  
标签:true scripts Makefile 内核 linux arch arm boot

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:
image
编译完成后如下图:
image
image
image
先编译出zimage,各种dtb,最后编译出ko。

2 kernel源码目录结构分析

linux内核源码编译后目录结构如下:
image

架构 描述
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 为例:
image
这些子目录用于控制系统引导、系统调用、动态调频、主频设置等。

2.1.1 arch/arm/configs

arch/arm/configs 目录是不同平台的默认配置文件:xxx_defconfig:
image
I.MX6U-ALPHA 开发板的默认配置文件:arch/arm/configs/imx_v7_defconfig

2.1.2 arch/arm/boot/dts

arch/arm/boot/dts 目录里面是对应开发平台的设备树文件, I.MX6U-ALPHA 开发板对应的设备树文件如下:
image

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 命令输出详细程度

image
和uboot完全一样。make -s设置成静默输出,将会silent_输出,不打印任何提示信息。如下:
image

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:
image
其中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 核心变量导出

image

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 配置变量

image
同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。
image

build 定义在文件 scripts/Kbuild.include 中,值为:
build := -f $(srctree)/scripts/Makefile.build obj
image

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
image
在顶层 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

image
回到顶层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 文件。

image

标签:true,scripts,Makefile,内核,linux,arch,arm,boot
From: https://www.cnblogs.com/fuzidage/p/17984739

相关文章

  • Linux新手村必备!这些常用操作命令你掌握了吗?
    在计算机的世界里,Linux操作系统以其强大的功能和灵活性受到了广大程序员和IT爱好者的喜爱。然而,对于初学者来说,Linux的操作命令可能会显得有些复杂和难以理解。今天,我们就来一起探索一些Linux常用操作命令,让你的计算机操作更加流畅。一、目录操作首先带大家了解一下Linux系统目......
  • Linux命令:passwd 修改用户密码
    passwd命令详细使用passwd修改用户账户的密码。普通用户只能修改自己的密码,超级管理员可以修改其他用户账户的密码。passwd也会修改『账户』或者密码的有效期限。1.超级管理员修改其他用户密码$sudopasswduser1输入两次密码,两次需要相同。密码不能少于8个字符。2.普......
  • 转载——Linux/Macos环境下使用 steamcommunity 302 教程
    原博:https://www.dogfight360.com/blog/2319/steamcommunity302后端使用caddy,在生成所有配置文件后可直接迁移到Linux/Macos环境下使用1.首先要在Windows环境/Wine下运行steamcommunity302并在设置里打勾需要开启的功能,然后正常启动服务 2.前往caddy/release页下载......
  • Linux 下安装 Jenkins 和使用 配置
    安装:要在Linux上安装Jenkins并进行配置,您可以按照以下步骤进行操作:步骤1:安装JavaJenkins依赖于Java环境,因此首先需要在您的Linux系统上安装Java。可以使用以下命令检查是否已安装Java:java-version如果您看到Java的版本信息,则已经安装了Java。否则,您可以按照以下步骤安装Java:sudo......
  • 【原创】linux为什么不是实时操作系统
    一、什么是实时操作系统(RTOS)?可参见本博客之前的文章:什么是实时实时的分类常见的RTOSlatency和jitter总结一下,实时其实说的是系统响应事件需要的时间的确定性,时间必须确定,打死都不能超过这个时间。二、linux为什么不是实时操作系统?为了确保系统的实时性,即事件响应产生结果......
  • Linux命令:useradd添加用户
    useradd命令的详细使用1.创建一个默认配置的用户$useradduser1创建一个用户,登陆名为user1,『uid』,『group』,『gid』,『shell』,『home_dir』都采用默认值。可以通过$useradd-D来查看配置默认值。uid:用户账户的uid,默认值取决于/etc/login.defs文件中定义的U......
  • Linux网络编程基础API
    目录socket地址API创建socket命名socket监听socket接收连接发起连接关闭连接数据读写带外标记地址信息函数socket选项网络信息APIsocket地址API主机字节序和网络字节序在Linux系统中,主机字节序(HostByteOrder)和网络字节序(NetworkByteOrder)是两个重要的概念。主机字节序......
  • NOI Linux 系统使用的笔记
    我为什么现在才会用啊。不知道是谁去年THUSC时不会用,导致用代码没法编译运行。终端的指令首先,几个常用的编译指令,在终端(Terminal)里使用。编译指令ls(list),会列出当前所在文件夹的所有子文件夹。cdname,访问子文件夹特别的,返回到上级目录夹用以下指令:cd..编辑器接下......
  • petalinux 报错总结
    Failedtomenuconfigprojectcomponent....解决办法此处是由于Terminal(终端)的界面太窄导致的,把Terminal(终端)界面拉宽即可;重新执行命令【petalinux-config--get-hw-description=*.xsa“path”】后,可以看到配置界面弹出来了,且没有了刚刚的错误。do_rootfs:Thepostinstall......
  • 【linux学习】使用_nmon_工具对系统进行监控
    【linux学习】使用_nmon_工具对系统进行监控原创:厦门微思网络 【微思2002年成立,专业IT认证培训21年!】 我们主要课程:思科、华为、红帽、ORACLE、VMware、CISP、PMP等认证培训及考证。......