以下内核Makefile术语之间有何区别:vmLinux,vmlinuz,vmlinux.bin,zimage和bzimage?


50

浏览内核Makefile时,发现了这些术语。所以,我想知道是什么样的区别vmlinuxvmlinuzvmlinux.binzimagebzimage


我认为zimage是gz压缩而bzimage是bz压缩...太大了,命名,afaik都不意味着该死的东西。但我可能是错的。
xenoterracide 2011年

Answers:


59

虚拟机

这是Linux内核,具有静态链接的可执行文件格式。通常,您不必担心此文件,它只是引导过程的中间步骤。

原始vmlinux文件可能对于调试目的很有用。

vmlinux.bin

与vmlinux相同,但采用可引导的原始二进制文件格式。所有符号和重定位信息都将被丢弃。vmlinux由产生objcopy -O binary vmlinux vmlinux.bin

vmlinuz

vmlinux文件通常使用压缩zlib。从2.6.30开始LZMAbzip2也可用。通过为vmlinuz添加更多引导和解压缩功能,可以使用该映像来引导具有vmlinux内核的系统。vmlinux的压缩可以通过zImage或bzImage进行。

该函数decompress_kernel()在启动时处理vmlinuz的解压缩,一条消息表明:

Decompressing Linux... done
Booting the kernel.

zImagemake zImage

这是小内核的旧格式(压缩后小于512KB)。在启动时,此映像被加载到内存不足的位置(RAM的前640KB)。

bzImagemake 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

decompress_kernel()函数实现位于哪里?
森,

2
它坐落在/arch/$ARCH/boot/compressed/misc.c,在这里看到:lxr.linux.no/#linux+v2.6.37/arch/x86/boot/compressed/...
摇动

8

做详细的内核构建并搜索文件

这种方法可以提供一些见解,永远不会过时,并且将帮助您轻松地找到构建系统的哪个部分在做什么。

一旦具有生成其中一个文件的构建配置,就可以使用:

make V=1 |& tee f.log

init/main.c如果您以前已经构建过,请修改一些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/bzImagearch/x86/boot/vmlinux.binTODO和其他文件中生成TODO的build确切含义是什么?

如果我们遵循,arch/x86/boot/vmlinux.bin我们将看到它只是objcopy来自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 -hlSrpiggy.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"

另请参阅:https : //stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc/36295692#36295692

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.oinit/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

aarch64 arch/arm64/boot/Image

只是未压缩objcopyvmlinux

objcopy  -O binary -R .note -R .note.gnu.build-id -R .comment -S vmlinux arch/arm64/boot/Image

vmlinux 通过精简归档文件,可以用与x86完全相同的方式获得该文件。

arch/arm/boot/zImage

与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



1

vmlinux的

一种非压缩且不可引导的Linux内核文件格式,仅是产生的中间步骤vmlinuz

vmlinuz
一个可压缩且可引导的Linux内核文件。它实际上是zImagebzImage文件。

zImage
对于旧内核,只适合640kram大小。

bzImage的
Big zImage640kRAM大小限制,可以大得多。

请参考此文档:vmlinuz定义


1

bzImage是与PC BIOS配合使用的x86体系结构的目标。相比之下,zImage是特定于体系结构的目标,最常用于嵌入式设备,并且可以与它们的引导程序配合使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.