カーネルMakefileを閲覧しているときに、これらの用語を見つけました。 vmlinux
、vmlinuz
、vmlinux.bin
、zimage
とbzimage
の違いは何ですか?
vmlinux
これは、静的にリンクされた実行可能ファイル形式のLinuxカーネルです。通常、このファイルについて心配する必要はありません。これは、ブート手順の中間段階にすぎません。
生のvmlinuxファイルは、デバッグの目的で役立つ場合があります。
vmlinux.bin
Vmlinuxと同じですが、起動可能なrawバイナリファイル形式です。すべてのシンボルと再配置情報は破棄されます。 _objcopy -O binary vmlinux vmlinux.bin
_によってvmlinux
から生成されます。
vmlinuz
Vmlinuxファイルは通常、zlib
で圧縮されます。 2.6.30以降、LZMA
および_bzip2
_も使用可能です。 vmlinuzにさらにブートおよび解凍機能を追加することにより、イメージを使用してvmlinuxカーネルでシステムをブートできます。 vmlinuxの圧縮は、zImageまたはbzImageで発生する可能性があります。
関数decompress_kernel()
は、起動時にvmlinuzの解凍を処理します。メッセージは次のことを示します。
_Decompressing Linux... done
Booting the kernel.
_
zImage(_make zImage
_)
これは小さなカーネルの古い形式です(圧縮、512KB未満)。ブート時に、このイメージはメモリのローに読み込まれます(RAMの最初の640KB)。
bzImage(_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
_
詳細なカーネルビルドを実行し、ファイルを検索します
このアプローチは、ある程度の洞察を提供し、決して古くなることはなく、ビルドシステムのどの部分が何をしているかを簡単に見つけるのに役立ちます。
ファイルの1つを生成するビルド構成を作成したら、次のコマンドでビルドします。
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のインクリメンタルリンクからシンアーカイブに移動しました: 53959624#53959624
完全なログ解釈
詳細なビルドログをバックアップから読み取り始めると、最初に次のことがわかります。
ln -fsn ../../x86/boot/bzImage ./Arch/x86_64/boot/bzImage
したがって、これら2つはシンボリックリンクされています。
次に、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
をフォローすると、Arch/x86/boot/compressed/vmlinux
からのobjcopy
にすぎないことがわかります。
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
分析は this config を含み、CONFIG_KERNEL_GZIP=y
を含みます。
aarch64 Arch/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
圧縮されたvmlinux
を備えたX86に非常に似ていますが、魔法の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
それはすべてここにあります: http://en.wikipedia.org/wiki/Vmlinux
vmlinux:
圧縮されておらず、起動できないLinuxカーネルファイル形式であり、vmlinuz
を生成するための中間ステップにすぎません。
vmlinuz:
圧縮された起動可能なLinuxカーネルファイル。実際にはzImage
またはbzImage
ファイルです。
zImage:
古いカーネルの場合、ちょうどフィットします640k
RAMサイズ。
bzImage:Big zImage
、 番号 640k
ramサイズ制限、はるかに大きくすることができます。
このドキュメントを参照してください: vmlinuz定義 。
bzImageは、PC BIOSで動作するx86アーキテクチャに使用されるターゲットです。対照的に、zImageは、組み込みデバイスに最も一般的に使用されるアーキテクチャ固有のターゲットであり、それらのブートローダーで適切に機能します。