在浏览内核 Makefile 时,我发现了这些术语。所以我想知道vmlinux
, vmlinuz
, vmlinux.bin
, zimage
&之间有什么区别bzimage
?
答案1
虚拟机Linux
这是静态链接可执行文件格式的 Linux 内核。一般来说,您不必担心这个文件,它只是引导过程中的一个中间步骤。
原始 vmlinux 文件对于调试目的可能很有用。
虚拟机linux.bin
与 vmlinux 相同,但采用可引导的原始二进制文件格式。所有符号和重定位信息都将被丢弃。vmlinux
由生成objcopy -O binary vmlinux vmlinux.bin
。
虚拟机
vmlinux 文件通常用zlib
.自 2.6.30 起LZMA
也bzip2
可用。通过向 vmlinuz 添加进一步的引导和解压缩功能,该映像可用于引导具有 vmlinux 内核的系统。 vmlinux 的压缩可以通过 zImage 或 bzImage 进行。
该函数decompress_kernel()
在启动时处理 vmlinuz 的解压缩,一条消息表明:
Decompressing Linux... done
Booting the kernel.
z图像( make zImage
)
这是小内核的旧格式(压缩后,低于 512KB)。启动时,该映像会加载到内存较低的位置(RAM 的前 640KB)。
bz图像( make bzImage
)
大 zImage(这与 无关bzip2
)是在内核增长并处理更大图像(压缩后超过 512KB)时创建的。图像被加载到内存的高位(1MB RAM 以上)。由于当今的内核远远超过 512KB,因此这通常是首选方式。
对 Ubuntu 10.10 的检查显示:
ls -lh /boot/vmlinuz-$(uname -r)
-rw-r--r-- 1 root root 4.1M 2010-11-24 12:21 /boot/vmlinuz-2.6.35-23-generic
file /boot/vmlinuz-$(uname -r)
/boot/vmlinuz-2.6.35-23-generic: Linux kernel x86 boot executable bzImage, version 2.6.35-23-generic (buildd@rosea, RO-rootFS, root_dev 0x6801, swap_dev 0x4, Normal VGA
答案2
进行详细的内核构建并搜索文件
这种方法可以提供一些洞察力,永远不会过时,并且将帮助您轻松找到构建系统的哪个部分正在做什么。
一旦您拥有生成其中一个文件的构建配置,请使用以下命令进行构建:
make V=1 |& tee f.log
如果您之前已经构建过,请修改某些 C 文件的注释以强制重新链接(例如,这init/main.c
是一个好的链接)。
现在,检查f.log
并搜索感兴趣的图像。
例如,在 v4.19 上我们将得出结论:
init/main.c
|
| gcc -c
|
v
init/.tmp_main.o
|
| CONFIG_MODVERSIONS stuff
|
v
init/main.o
|
| ar T (thin archive)
|
v
init/built-in.a
|
| ar T (thin archive)
|
v
built-in.a
|
| ld
|
v
vmlinux (regular ELF file)
|
| objcopy
|
v
arch/x86/boot/compressed/vmlinux.bin
|
| GZIP
|
v
arch/x86/boot/compressed/vmlinux.bin.gz
|
| .incbin
|
v
arch/x86/boot/compressed/piggy.S
|
| gcc -c
|
v
arch/x86/boot/compressed/piggy.o
|
| ld
|
v
arch/x86/boot/compressed/vmlinux (regular ELF file with gzipped code)
|
| objcopy
|
v
arch/x86/boot/vmlinux.bin
|
| arch/x86/boot/tools/build.c
|
v
arch/x86/boot/bzImage
薄档案在以下位置提到:https://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries/27676016#27676016它们是仅指向其他档案/对象而不是复制它们的档案。
在 v4.9 中,内核从增量链接转移到精简存档,如下所述:https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624
完整的日志解释
当我们开始从备份中读取详细的构建日志时,我们首先看到:
ln -fsn ../../x86/boot/bzImage ./arch/x86_64/boot/bzImage
所以这两个只是符号链接。
然后我们进一步搜索x86/boot/bzImage
并发现:
arch/x86/boot/tools/build \
arch/x86/boot/setup.bin \
arch/x86/boot/vmlinux.bin \
arch/x86/boot/zoffset.h \
arch/x86/boot/bzImage
arch/x86/boot/tools/build
是一个可执行文件,所以我们运行它,查看帮助消息:
Usage: build setup system zoffset.h image
和 grep 查找源:
arch/x86/boot/tools/build.c
arch/x86/boot/bzImage
那么这个工具必须从其他文件生成arch/x86/boot/vmlinux.bin
TODO 到底有什么意义呢build
?
如果我们遵循,arch/x86/boot/vmlinux.bin
我们会发现它只是一个objcopy
from arch/x86/boot/compressed/vmlinux
:
objcopy \
-O binary \
-R .note \
-R .comment \
-S arch/x86/boot/compressed/vmlinux \
arch/x86/boot/vmlinux.bin
只是arch/x86/boot/compressed/vmlinux
一个普通的 ELF 文件:
ld \
-m elf_x86_64 \
-z noreloc-overflow \
-pie \
--no-dynamic-linker \
-T arch/x86/boot/compressed/vmlinux.lds \
arch/x86/boot/compressed/head_64.o \
arch/x86/boot/compressed/misc.o \
arch/x86/boot/compressed/string.o \
arch/x86/boot/compressed/cmdline.o \
arch/x86/boot/compressed/error.o \
arch/x86/boot/compressed/piggy.o \
arch/x86/boot/compressed/cpuflags.o \
arch/x86/boot/compressed/early_serial_console.o \
arch/x86/boot/compressed/kaslr.o \
arch/x86/boot/compressed/kaslr_64.o \
arch/x86/boot/compressed/mem_encrypt.o \
arch/x86/boot/compressed/pgtable_64.o \
-o arch/x86/boot/compressed/vmlinux
ls -hlSr
说这piggy.o
是迄今为止最大的文件,所以我们搜索它,它必须来自:
gcc \
-Wp,-MD,arch/x86/boot/compressed/.piggy.o.d \
-nostdinc \
-Ilinux/arch/x86/include \
-I./arch/x86/include/generated \
-Ilinux/include \
-I./include \
-Ilinux/arch/x86/include/uapi \
-I./arch/x86/include/generated/uapi \
-Ilinux/include/uapi \
-I./include/generated/uapi \
-include linux/include/linux/kconfig.h \
-D__KERNEL__ \
-m64 \
-O2 \
-fno-strict-aliasing \
-fPIE \
-DDISABLE_BRANCH_PROFILING \
-mcmodel=small \
-mno-mmx \
-mno-sse \
-ffreestanding \
-fno-stack-protector \
-Wno-pointer-sign \
-D__ASSEMBLY__ \
-c \
-o arch/x86/boot/compressed/.tmp_piggy.o \
arch/x86/boot/compressed/piggy.S
.tmp_
前缀解释如下。
arch/x86/boot/compressed/piggy.S
包含:
.incbin "arch/x86/boot/compressed/vmlinux.bin.gz"
arch/x86/boot/compressed/vmlinux.bin.gz
来自:
cat arch/x86/boot/compressed/vmlinux.bin arch/x86/boot/compressed/vmlinux.relocs | \
gzip -n -f -9 > arch/x86/boot/compressed/vmlinux.bin.gz
它来自:
objcopy -R .comment -S vmlinux arch/x86/boot/compressed/vmlinux.bin
它来自:
LD vmlinux
它的作用是:
ld \
-m elf_x86_64 \
-z max-page-size=0x200000 \
--emit-relocs \
--build-id \
-o vmlinux \
-T ./arch/x86/kernel/vmlinux.lds \
--whole-archive \
built-in.a \
--no-whole-archive \
--start-group \
lib/lib.a \
arch/x86/lib/lib.a \
--end-group \
.tmp_kallsyms2.o
vmlinux
很大,但根据 ,所有显示的对象都很小ls -l
,所以我研究并了解了一个ar
我不知道的新功能:薄档案。
在:
AR built-in.a
构建的作用是:
ar \
rcsTPD \
built-in.a \
arch/x86/kernel/head_64.o \
arch/x86/kernel/head64.o \
arch/x86/kernel/ebda.o \
arch/x86/kernel/platform-quirks.o \
init/built-in.a \
usr/built-in.a \
arch/x86/built-in.a \
kernel/built-in.a \
certs/built-in.a \
mm/built-in.a \
fs/built-in.a \
ipc/built-in.a \
security/built-in.a \
crypto/built-in.a \
block/built-in.a \
lib/built-in.a \
arch/x86/lib/built-in.a \
drivers/built-in.a \
sound/built-in.a \
firmware/built-in.a \
arch/x86/pci/built-in.a \
arch/x86/power/built-in.a \
arch/x86/video/built-in.a \
net/built-in.a \
virt/built-in.a
T
指定精简存档。
然后我们可以看到所有子档案也很薄,例如,自从我修改后init/main.c
,我们有:
ar \
rcSTPD \
init/built-in.a \
init/main.o \
init/version.o \
init/do_mounts.o \
init/do_mounts_initrd.o \
init/initramfs.o \
init/calibrate.o \
init/init_task.o
最终通过如下命令来自 C 文件:
gcc \
-Wp,-MD,init/.main.o.d \
-c \
-o \
init/.tmp_main.o \
/work/linux-kernel-module-cheat/submodules/linux/init/main.c
我找不到踩在木头上的地方init/.tmp_main.o
,init/main.o
真遗憾……
git grep '\.tmp_'
我们看到它可能来自scripts Makefile.build
并链接到CONFIG_MODVERSIONS
我启用的:
ifndef CONFIG_MODVERSIONS
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
else
# When module versioning is enabled the following steps are executed:
# o compile a .tmp_<file>.o from <file>.c
# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
# not export symbols, we just rename .tmp_<file>.o to <file>.o and
# are done.
# o otherwise, we calculate symbol versions using the good old
# genksyms on the preprocessed source and postprocess them in a way
# that they are usable as a linker script
# o generate <file>.o from .tmp_<file>.o using the linker to
# replace the unresolved symbols __crc_exported_symbol with
# the actual value of the checksum generated by genksyms
cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
cmd_modversions_c = \
if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
$(LD) $(KBUILD_LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
-T $(@D)/.tmp_$(@F:.o=.ver); \
rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \
else \
mv -f $(@D)/.tmp_$(@F) $@; \
fi;
endif
分析完成这个配置其中包含CONFIG_KERNEL_GZIP=y
。
架构64arch/arm64/boot/Image
只是未压缩objcopy
的vmlinux
:
objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image
vmlinux
通过精简档案以与 x86 基本完全相同的方式获得。
arch/arm/boot/zImage
与带有 zipped 的 X86 非常相似vmlinux
,但没有神奇的build.c
步骤。调用链总结:
objcopy -O binary -R .comment -S arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage
ld \
-EL \
--defsym _kernel_bss_size=469592 \
-p \
--no-undefined \
-X \
-T arch/arm/boot/compressed/vmlinux.lds \
arch/arm/boot/compressed/head.o \
arch/arm/boot/compressed/piggy.o \
arch/arm/boot/compressed/misc.o \
arch/arm/boot/compressed/decompress.o \
arch/arm/boot/compressed/string.o \
arch/arm/boot/compressed/hyp-stub.o \
arch/arm/boot/compressed/lib1funcs.o \
arch/arm/boot/compressed/ashldi3.o \
arch/arm/boot/compressed/bswapsdi2.o \
-o arch/arm/boot/compressed/vmlinux
gcc \
-c \
-o arch/arm/boot/compressed/piggy.o \
linux/arch/arm/boot/compressed/piggy.S
.incbin "arch/arm/boot/compressed/piggy_data"
cat arch/arm/boot/compressed/../Image | gzip -n -f -9 > arch/arm/boot/compressed/piggy_data
objcopy -O binary -R .comment -S vmlinux arch/arm/boot/Image
QEMU v4.0.0 可以从 bzImage 启动,但不能从 vmlinux 启动
这是另一个重要的实际区别:https://superuser.com/questions/1451568/booting-an-uncompressed-kernel-in-qemu
答案3
我通常不使用维基百科来理解这样的事情,但它对于虚拟机Linux。
随着 Linux 内核的成熟,用户生成的内核的大小超出了某些体系结构所施加的限制,在这些体系结构中,可用于存储压缩内核代码的空间是有限的。 bzImage(大zImage)格式的开发是为了通过将内核分割到不连续的内存区域来克服这一限制。
bzImage 使用 gzip 进行压缩,直到 Linux 2.6.30
bzImage 文件采用特定格式。它包含串联的 bootsect.o + setup.o + Misc.o + Piggy.o。 Piggy.o 在其数据部分包含 gzip 压缩的 vmlinux 文件。
我知道我只回答了部分问题 - 我自己仍在尝试理解它。
答案4
bz图像是用于与 PC BIOS 配合使用的 x86 架构的目标。相比之下,z图像是最常用于嵌入式设备的特定于体系结构的目标,并且与引导加载程序配合良好。