当前位置: 首页 > news >正文

imx6ull-系统移植篇18——linux顶层 Makefile(下)

目录

前言

make 过程

目标 _all

vmlinux

head-y

init-y、 drivers-y 和 net-y

libs-y

core-y

vmlinux.lds

函数 if_changed

vmliux_link函数

built-in.o 文件编译生成过程

vmlinux-deps

vmlinux-dirs

举例

make zImage 过程

vmlinux、 Image, zImage、 uImage 的区别

1. vmlinux​​

2. Image​​

3. zImage​​

4. uImage​​

make zImage


前言

在上一讲内容:linux顶层 Makefile(上),我们简单分析了linux内核顶层Makefile源码,分析了make xxx_defconfig 过程、Makefile.build 脚本。

这一讲内容,我们继续分析linux顶层 Makefile:make 过程、built-in.o 文件编译生成过程、make zImage 过程。

make 过程

使用命令“make xxx_defconfig”配置好 Linux 内核以后就可以使用“make”或者“make all”命令进行编译。

目标 _all

顶层 Makefile 有如下代码:

# 声明伪目标(防止与同名文件冲突)
PHONY := _all# 默认目标入口(直接make时执行的目标)
_all:[...]# 定义all目标为伪目标
PHONY += all# 根据是否外部模块构建设置依赖链
ifeq ($(KBUILD_EXTMOD),)# 常规内核构建:_all依赖all_all: all
else# 外部模块构建:_all仅需构建modules_all: modules
endif[...]# all目标的最终定义(在文件后部)
all: vmlinux[...]

默认目标_all 依赖 all,目标 all 依赖 vmlinux,所以接下来的重点就是 vmlinux。

vmlinux

顶层 Makefile 中有如下代码:

# 导出给 link-vmlinux.sh 脚本使用的符号
export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)      # 初始化段目标文件
export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y)  # 主段目标文件
export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds  # 链接脚本路径
export LDFLAGS_vmlinux                                 # 特殊链接标志
export KBUILD_ALLDIRS := $(sort $(filter-out arch/%,$(vmlinux-alldirs)) arch Documentation include samples scripts tools virt)  # 构建涉及的所有目录# vmlinux 的依赖项(链接脚本+所有目标文件)
vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)# 定义链接命令模板
cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux)
quiet_cmd_link-vmlinux = LINK $@# vmlinux 目标规则(最终生成内核镜像)
vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE# 可选:头文件检查ifdef CONFIG_HEADERS_CHECK$(Q)$(MAKE) -f $(srctree)/Makefile headers_checkendif# 可选:构建示例代码ifdef CONFIG_SAMPLES$(Q)$(MAKE) $(build)=samplesendif# 可选:构建文档ifdef CONFIG_BUILD_DOCSRC$(Q)$(MAKE) $(build)=Documentationendif# 可选:生成GDB调试脚本ifdef CONFIG_GDB_SCRIPTS$(Q)ln -fsn `cd $(srctree) && /bin/pwd`/scripts/gdb/vmlinux-gdb.pyendif# 执行实际链接操作+$(call if_changed,link-vmlinux)

由代码可知:

vmlinux 的依赖为: scripts/link-vmlinux.sh、 $(head-y) 、 $(init-y)、 $(core-y) 、$(libs-y) 、 $(drivers-y) 、 $(net-y)、 arch/arm/kernel/vmlinux.lds 和 FORCE。

重点来看一下$(head-y) 、 $(init-y)、 $(core-y) 、 $(libs-y) 、 $(drivers-y) 和$(net-y)这六个变量的值。

head-y

head-y 定义在文件 arch/arm/Makefile 中,内容如下:

head-y := arch/arm/kernel/head$(MMUEXT).o
  • 当不使能 MMU 的话: MMUEXT=-nommu,
  • 如果使能 MMU 的话:MMUEXT为空,

因此 head-y 最终的值为:

head-y = arch/arm/kernel/head.o

init-y、 drivers-y 和 net-y

在顶层 Makefile 中有如下代码:

# 阶段1:定义原始目录列表(初始化变量)
init-y := init/               # 初始化代码目录
drivers-y := drivers/ sound/ firmware/  # 驱动相关目录
net-y := net/                 # 网络协议栈目录
[...其他目录定义...]# 阶段2:转换为built-in.o目标(实际构建目标)
init-y := $(patsubst %/, %/built-in.o, $(init-y))      # init/built-in.o
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)) # drivers/built-in.o sound/built-in.o
net-y := $(patsubst %/, %/built-in.o, $(net-y))        # net/built-in.o

init-y、drivers-y 和 net-y 最终的值为:

init-y = init/built-in.o
drivers-y = drivers/built-in.o sound/built-in.o firmware/built-in.o
net-y = net/built-in.o

libs-y

libs-y 基本和 init-y 一样,在顶层 Makefile 中存在如下代码:

# 原始定义:库目录
libs-y := lib/   # 基础库代码目录# 转换为两种目标格式:
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))    # 生成静态库文件(lib/lib.a)
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y)) # 生成合并目标文件(lib/built-in.o)# 最终合并两种目标
libs-y := $(libs-y1) $(libs-y2)  # 同时包含lib.a和built-in.o

可知, libs-y 应该等于“lib.a built-in.o”。

再加上, arch/arm/Makefile 中会向 libs-y 中追加一些值,代码如下:

libs-y := arch/arm/lib/ $(libs-y)

展开以后为:

libs-y = arch/arm/lib lib/

所以,libs-y 最终应该为:

libs-y = arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o

core-y

core-y 和 init-y 也一样,在顶层 Makefile 中有如下代码:

core-y := usr/
......
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

在 arch/arm/Makefile 中会对 core-y 进行追加,代码如下:

# 条件性包含浮点运算单元支持
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/      # 软件浮点模拟
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)     # 快速浮点模拟(已废弃)
core-$(CONFIG_VFP) += arch/arm/vfp/              # 硬件向量浮点# 虚拟化支持
core-$(CONFIG_XEN) += arch/arm/xen/             # Xen 虚拟化
core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/    # KVM 虚拟化# 其他内核特性
core-$(CONFIG_VDSO) += arch/arm/vdso/           # 虚拟动态共享对象# 强制包含的ARM核心目录(无条件包含)
core-y += arch/arm/kernel/                      # 核心内核代码
core-y += arch/arm/mm/                          # 内存管理
core-y += arch/arm/common/                      # 通用ARM代码
core-y += arch/arm/probes/                      # 动态探针
core-y += arch/arm/net/                         # 网络优化
core-y += arch/arm/crypto/                      # 加密算法
core-y += arch/arm/firmware/                    # 固件支持# 包含机器/平台特定目录
core-y += $(machdirs) $(platdirs)               # 由arch/arm/Makefile定义

根据不同的配置向 core-y 追加不同的值,比如使能 VFP 的话就会在.config中有 CONFIG_VFP=y 这一行,那么 core-y 就会追加“arch/arm/vfp/”。

在顶层 Makefile 中有如下一行:

core-y := $(patsubst %/, %/built-in.o, $(core-y))

经过上述代码的转换,最终 core-y 的值为:

   core-y = 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

关于 head-y 、 init-y、 core-y 、 libs-y 、 drivers-y 和 net-y 这 6 个变量,都是一些 built-in.o 或.a 等文件,这个和 uboot 一样,都是将相应目录中的源码文件进行编译,然后在各自目录下生成 built-in.o 文件,有些生成了.a 库文件。最终将这些 built-in.o 和.a 文件进行链接即可形成 ELF 格式的可执行文件,也就是 vmlinux。

vmlinux.lds

但是链接是需要链接脚本的, vmlinux 的依赖 arch/arm/kernel/vmlinux.lds 就是整个 Linux 的链接脚本。

还记得上面提到的代码:

    # 执行实际链接操作+$(call if_changed,link-vmlinux)

表示将$(call if_changed,link-vmlinux)的结果作为最终生成 vmlinux 的命令,

  • 前面的“+”表示该命令结果不可忽略。
  • $(call if_changed,link-vmlinux)是调用函数 if_changed,
  • link-vmlinux 是函数 if_changed 的参数,
函数 if_changed

函数 if_changed 定义在文件 scripts/Kbuild.include 中,如下所示:

if_changed = $(if $(strip $(any-prereq) $(arg-check)), \@set -e; \                                     # 出错立即退出$(echo-cmd) $(cmd_$(1)); \                     # 打印并执行命令printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)  # 保存命令记录
  • any-prereq 用于检查依赖文件是否有变化,如果依赖文件有变化那么 any-prereq 就不为空,否则就为空。
  • arg-check 用于检查参数是否有变化,如果没有变化那么 arg-check 就为空。
  • “@set -e”告诉 bash,如果任何语句的执行结果不为 true(也就是执行出错)的话就直接退出。
  • $(echo-cmd)用于打印命令执行过程,比如在链接 vmlinux 的时候就会输出“LINK vmlinux”。
  • $(cmd_$(1))中的$(1)表示参数,也就是 link-vmlinux,因此$(cmd_$(1))表示执行 cmd_link-vmlinux 的内容。

cmd_link-vmlinux 在顶层 Makefile 中有如下所示定义:

# 详细版链接命令(实际执行)
cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux)# 简洁版显示(默认输出)
quiet_cmd_link-vmlinux = LINK $@

命令组成要素​

变量/参数

作用

$(CONFIG_SHELL)

确保使用正确的shell解释器(通常为bash)

$<

第一个依赖文件(即scripts/link-vmlinux.sh)

$(LD)

链接器路径(如arm-linux-gnueabi-ld)

$(LDFLAGS)

通用链接标志(如-m elf_x86_64

$(LDFLAGS_vmlinux)

内核专用链接标志(如-Ttext 0x80008000

cmd_link-vmlinux 最终的值为:

cmd_link-vmlinux = /bin/bash scripts/link-vmlinux.sh arm-linux-gnueabihf-ld -EL -p --noundefined -X --pic-veneer --build-id

cmd_link-vmlinux 会调用 scripts/link-vmlinux.sh 这个脚本来链接出 vmlinux。

vmliux_link函数

在 linkvmlinux.sh 中有如下所示代码:

vmlinux_link() {# 1. 链接脚本路径设置local lds="${objtree}/${KBUILD_LDS}"# 2. 常规架构链接(非UML)if [ "${SRCARCH}" != "um" ]; then${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \-T ${lds} ${KBUILD_VMLINUX_INIT} \--start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1}# 3. 用户模式(UML)特殊处理else${CC} ${CFLAGS_vmlinux} -o ${2} \-Wl,-T,${lds} ${KBUILD_VMLINUX_INIT} \-Wl,--start-group \${KBUILD_VMLINUX_MAIN} \-Wl,--end-group \-lutil ${1}rm -f linuxfi
}# 实际调用
vmlinux_link "${kallsymso}" vmlinux

vmliux_link 就是最终链接出 vmlinux 的函数,

  • 链接脚本为lds= ./arch/arm/kernel/vmlinux.lds ,
  • 需要链接的文件由变量 KBUILD_VMLINUX_INITKBUILD_VMLINUX_MAIN 来决定。

使用命令“make V=1”编译 Linux,会有如图所示的编译信息:

总结一下:

make 的过程,重点就是将各个子目录下的 built-in.o、 .a 等文件链接在一起,最终生成 vmlinux 这个 ELF 格式的可执行文件。

链接脚本为 arch/arm/kernel/vmlinux.lds,链接过程是由shell脚本scripts/link-vmlinux.s来完成的。

built-in.o 文件编译生成过程

各个子目录下的builtin.o、 .a 等文件又是如何编译出来的呢?

vmlinux-deps
vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE

可知, vmliux 依赖 vmlinux-deps

而 vmlinux-deps= $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)

最终 vmlinux-deps 的值如下:

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

除了 arch/arm/kernel/vmlinux.lds 以外,其他都是要编译链接生成的。

在顶层 Makefile 中有如下代码:

$(sort $(vmlinux-deps)): $(vmlinux-dirs) ;

sort 是排序函数,用于对 vmlinux-deps 的字符串列表进行排序,并且去掉重复的单词。

可以看出 vmlinux-deps 依赖 vmlinux-dirs。

vmlinux-dirs

vmlinux-dirs 也定义在顶层 Makefile 中,定义如下:

vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \$(core-y) $(core-m) $(drivers-y) $(drivers-m) \$(net-y) $(net-m) $(libs-y) $(libs-m)))

vmlinux-dirs 看名字就知道和目录有关,此变量保存着生成 vmlinux 所需源码文件的目录,
值如下:

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

在顶层 Makefile 中有如下代码:

$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@

目标 vmlinux-dirs 依赖 prepare 和 scripts。

build 的值为“-f ./scripts/Makefile.build obj”,代入上面代码展开为:

@ make -f ./scripts/Makefile.build obj=$@

$@表示目标文件,也就是 vmlinux-dirs 的值,将 vmlinux-dirs 中的这些目录全部带入到命令中,结果如下:

@ make -f ./scripts/Makefile.build obj=init
@ make -f ./scripts/Makefile.build obj=usr
@ make -f ./scripts/Makefile.build obj=arch/arm/vfp
@ make -f ./scripts/Makefile.build obj=arch/arm/vdso
@ make -f ./scripts/Makefile.build obj=arch/arm/kernel
@ make -f ./scripts/Makefile.build obj=arch/arm/mm
@ make -f ./scripts/Makefile.build obj=arch/arm/common
@ make -f ./scripts/Makefile.build obj=arch/arm/probes
@ make -f ./scripts/Makefile.build obj=arch/arm/net
@ make -f ./scripts/Makefile.build obj=arch/arm/crypto
@ make -f ./scripts/Makefile.build obj=arch/arm/firmware
@ make -f ./scripts/Makefile.build obj=arch/arm/mach-imx
@ make -f ./scripts/Makefile.build obj=kernel
@ make -f ./scripts/Makefile.build obj=mm
@ make -f ./scripts/Makefile.build obj=fs
@ make -f ./scripts/Makefile.build obj=ipc
@ make -f ./scripts/Makefile.build obj=security
@ make -f ./scripts/Makefile.build obj=crypto
@ make -f ./scripts/Makefile.build obj=block
@ make -f ./scripts/Makefile.build obj=drivers
@ make -f ./scripts/Makefile.build obj=sound
@ make -f ./scripts/Makefile.build obj=firmware
@ make -f ./scripts/Makefile.build obj=net
@ make -f ./scripts/Makefile.build obj=arch/arm/lib
@ make -f ./scripts/Makefile.build obj=lib

这段代码展示了 Linux 内核构建系统如何通过递归调用 Makefile.build来构建各个子系统的过程。

举例

以“@ make -f ./scripts/Makefile.build obj=init”这个命令为例,讲解一下详细的运行过程。

默认目标为__build,__build 目标对应的规则如下

__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \$(subdir-ym) $(always)@:  # 空命令(实际工作由依赖项完成)

目标类型说明

目标变量

内容类型

典型示例

$(builtin-target)

内核核心目标

vmlinux

$(lib-target)

内核库文件

lib/lib.a

$(extra-y)

额外构建目标

init/version.o

$(obj-m)

可加载模块

drivers/net/ethernet.ko

$(modorder-target)

模块顺序文件

modules.order

$(subdir-ym)

需要递归构建的子目录

drivers/char fs/ext4

$(always)

总是构建的目标

include/generated/autoconf.h

make”命令是会编译所有的东西,包括 Linux内核镜像文件和一些模块文件。

如果只编译 Linux 内核镜像的话, __build 目标简化为:

__build: $(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)@:

builtin-target 这个依赖, 定义在文件 scripts/Makefile.build中,定义如下:

# 检查是否有需要构建的目标
ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)# 如果存在任何构建目标,则设置built-in.o路径builtin-target := $(obj)/built-in.o
endif

builtin-target 变量的值,为“$(obj)/built-in.o”,这就是这些 built-in.o 的来源了。

要生成 built-in.o,要求 obj-y、 obj-m、 obj-、 subdir-m 和 lib-target 这些变量不能全部为空。

built-in.o 是怎么生成的?在文件 scripts/Makefile.build 中有如下代码:

# 条件检查:是否需要生成built-in.o
ifdef builtin-target# 定义链接命令(静默版和完整版)quiet_cmd_link_o_target = LD $@cmd_link_o_target = $(if $(strip $(obj-y)), \# 非空obj-y:使用ld合并目标文件$(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) $(cmd_secanalysis), \# 空obj-y:创建空归档文件rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@)# 构建规则$(builtin-target): $(obj-y) FORCE$(call if_changed,link_o_target)  # 增量构建控制# 注册目标targets += $(builtin-target)
endif

builtin-target,依赖为 obj-y,命令为“$(call if_changed,link_o_target)”,也就是调用函数 if_changed,参数为 link_o_target,其返回值就是具体的命令。

调用cmd_link_o_target 所对应的命令,用 LD将某个目录下的所有.o 文件链接在一起,最终形成 built-in.o。

make zImage 过程

vmlinux、 Image, zImage、 uImage 的区别

在 Linux 内核构建系统中,vmlinuxImagezImage和 uImage是不同阶段生成的内核镜像文件,它们的主要区别如下:

镜像类型

格式

压缩

调试符号

引导方式

典型使用场景

vmlinux

ELF

不可直接引导

内核开发与调试

Image

Raw Binary

需 Bootloader

部分嵌入式系统

zImage

Self-extracting

通用 Bootloader

PC/小型嵌入式设备

uImage

U-Boot Wrapper

仅 U-Boot

U-Boot 嵌入式系统

1. vmlinux​

  • ​性质​​:原始未压缩的 ​​ELF 格式​​ 可执行文件

  • ​特点​​:

    • 包含完整的调试符号和重定位信息(文件体积最大)

    • 未经过任何压缩或打包处理

    • 直接由内核源码链接生成(ld链接所有 built-in.o

  • ​用途​​:

    • 内核调试(gdb可直接加载)

    • 生成其他镜像的基础文件

  • ​文件大小​​:约 20-500 MB(取决于配置)

  • ​生成命令​​:make vmlinux

2. Image​

  • ​性质​​:​​未压缩的原始内核镜像​​(Raw Binary)

  • ​特点​​:

    • 通过 objcopy从 vmlinux剥离调试信息生成

    • 保留纯二进制代码和数据(仍较大)

    • 部分架构(如 ARM)可能直接使用此格式

  • ​用途​​:

    • 某些嵌入式系统的直接加载

    • 生成 zImage/uImage的中间文件

  • ​文件大小​​:约 5-50 MB

  • ​生成路径​​:arch/arm/boot/Image

3. zImage​

  • ​性质​​:​​压缩后的内核镜像​​(自解压格式)

  • ​特点​​:

    • 使用 gzip压缩 Image生成(压缩率约 50-70%)

    • 包含自解压代码(Bootloader 加载后自动解压到内存)

    • 兼容性最广的通用格式

  • ​限制​​:

    • 大小受限(ARM 通常需 < 512KB)

    • 不支持附加信息(如 DTBs)

  • ​用途​​:

    • 传统 PC 或小型嵌入式设备

  • ​文件大小​​:约 2-10 MB

  • ​生成路径​​:arch/arm/boot/zImage

4. uImage​

  • ​性质​​:​​U-Boot 专用的封装格式​

  • ​特点​​:

    • 在 zImage基础上添加 ​​U-Boot 头信息​​(加载地址、入口点等)

    • 支持 CRC 校验和可选的加密

    • 专用于 U-Boot 引导加载程序

  • ​用途​​:
    • 使用 U-Boot 的嵌入式系统(如开发板)

    • ​文件大小​​:略大于 zImage(增加约 64B 头)

    • ​生成命令​​:make uImage # 需安装 U-Boot 的 mkimage 工具

make zImage

实际中,我们使用 zImage 或 uImage 这样的 Linux 内核镜像文件。

使用“ make”、“ make all”、“ make zImage”这些命令就可以编译出 zImage 镜像。

在arch/arm/Makefile 中有如下代码:

# 定义支持的启动镜像类型
BOOT_TARGETS = zImage Image xipImage bootpImage uImage# 所有启动镜像都依赖vmlinux
$(BOOT_TARGETS): vmlinux$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@

变量 BOOT_TARGETS 包含 zImage, Image, xipImage 等镜像文件。

BOOT_TARGETS 依赖 vmlinux,因此如果使用“make zImage”编译的 Linux 内核的话,首先肯定要先编译出 vmlinux。

比如要编译 zImage,那么命令展开以后如下所示:

@ make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/zImage

也就是使用 scripts/Makefile.build 文件来完成 vmlinux 到 zImage 的转换。

本讲的重点,在于vmlinux 的生成,最后将 vmlinux 压缩成我们最常用的 zImage 或 uImage 等文件。

http://www.lryc.cn/news/596562.html

相关文章:

  • API是什么,如何保障API安全?
  • Springboot和postman的使用
  • XSS内容分享
  • 智能泵房监控系统:物联网应用与智能管理解决方案
  • Qt中QObject类的核心作用与使用
  • Qt 事件处理机制深入剖析
  • List<UserInfo> list = new ArrayList<>();为什么要这样创建数组?
  • 如何用keepAlive实现标签页缓存
  • 从 COLMAP 到 3D Gaussian Splatting
  • 滑动窗口经典问题整理
  • langchain4j之RAG 检索增强生成
  • Linux操作系统之线程(六):线程互斥
  • TCP day39
  • 质量即服务:从测试策略到平台运营的全链路作战手册
  • 重生学AI第十九集:VGG16的使用以及模型的保存与加载
  • 【期末考试复习】计算机组成原理 - 直接补码阵列乘法器
  • 【接口自动化】pytest的基本使用
  • CSS+JavaScript 禁用浏览器复制功能的几种方法
  • web登录页面
  • 黑马点评练习题-给店铺类型查询业务添加缓存(String和List实现)
  • kafka4.0集群部署
  • 数据结构01:链表
  • docker compose 安装使用笔记
  • Docker实战:使用Docker部署TeamMapper思维导图工具
  • 【实时Linux实战系列】基于实时Linux的传感器网络设计
  • Spring Boot音乐服务器项目-登录模块
  • 【论文阅读】Fast-BEV: A Fast and Strong Bird’s-Eye View Perception Baseline
  • 基于VU13P的百G光纤FMC高性能处理板
  • Rust实战:决策树与随机森林实现
  • 板凳-------Mysql cookbook学习 (十二--------5)