GNU/Linux >> Znalost Linux >  >> Linux

Jaký je rozdíl mezi následujícími výrazy Makefile jádra:vmLinux, vmlinuz, vmlinux.bin, zimage &bzimage?

vmlinux

Toto je linuxové jádro ve staticky propojeném formátu spustitelného souboru. Obecně se o tento soubor nemusíte starat, je to jen mezikrok při zavádění.

Nezpracovaný soubor vmlinux může být užitečný pro účely ladění.

vmlinux.bin

Stejné jako vmlinux, ale ve formátu bootovatelného surového binárního souboru. Všechny symboly a informace o přemístění jsou vyřazeny. Vygenerováno z vmlinux podle objcopy -O binary vmlinux vmlinux.bin .

vmlinuz

Soubor vmlinux se obvykle komprimuje pomocí zlib . Od 2.6.30 LZMA a bzip2 jsou také k dispozici. Přidáním dalších možností zavádění a dekomprese do vmlinuz lze obraz použít k zavedení systému s jádrem vmlinux. Komprese vmlinuxu může probíhat pomocí zImage nebo bzImage.

Funkce decompress_kernel() zpracovává dekompresi vmlinuz při bootování, zpráva ukazuje toto:

Decompressing Linux... done
Booting the kernel.

zImage (make zImage )

Toto je starý formát pro malá jádra (komprimovaný, pod 512 kB). Při spouštění se tento obraz načte málo v paměti (prvních 640 kB paměti RAM).

bzImage (make bzImage )

Velký zImage (to nemá nic společného s bzip2 ), byl vytvořen, zatímco jádro rostlo a zpracovává větší obrázky (komprimované, přes 512 kB). Obrázek se načte vysoko v paměti (nad 1 MB RAM). Protože dnešní jádra mají mnohem více než 512 kB, je to obvykle preferovaný způsob.

Kontrola na Ubuntu 10.10 ukazuje:

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 ([email protected], RO-rootFS, root_dev 0x6801, swap_dev 0x4, Normal VGA

Proveďte podrobné sestavení jádra a vyhledejte soubory

Tento přístup může poskytnout určitý přehled, nikdy nezestárne a pomůže vám snadno zjistit, která část systému sestavení co dělá.

Jakmile budete mít konfiguraci sestavení, která generuje jeden ze souborů, sestavte pomocí:

make V=1 |& tee f.log

Upravte komentář k některému souboru C, abyste vynutili opětovné propojení (např. init/main.c je dobrý), pokud jste již dříve stavěli.

Nyní zkontrolujte f.log a vyhledejte obrázky, které vás zajímají.

Například ve verzi 4.19 dojdeme k závěru, že:

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

Tenké archivy jsou zmíněny na:https://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries/27676016#27676016 Jsou to archivy, které pouze ukazují na jiné archivy/objekty, místo aby je kopírovaly.

Jádro se ve verzi 4.9 přesunulo z inkrementálního linkování na tenké archivy, jak je popsáno na:https://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker/53959624#53959624

Úplná interpretace protokolu

Když začneme číst podrobné protokoly sestavení odzadu nahoru, nejprve uvidíme:

ln -fsn ../../x86/boot/bzImage ./arch/x86_64/boot/bzImage

takže tito dva jsou jen symbolicky propojeni.

Pak hledáme o něco dále x86/boot/bzImage a najděte:

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 je spustitelný soubor, takže jej spustíme, viz zpráva nápovědy:

Usage: build setup system zoffset.h image

a grep k nalezení zdroje:

arch/x86/boot/tools/build.c

Tento nástroj tedy musí generovat arch/x86/boot/bzImage od arch/x86/boot/vmlinux.bin a další soubory TODO jaký je smysl build přesně?

Pokud budeme postupovat podle arch/x86/boot/vmlinux.bin vidíme, že je to jen objcopy od arch/x86/boot/compressed/vmlinux :

objcopy \
-O binary \
-R .note \
-R .comment \
-S arch/x86/boot/compressed/vmlinux \
arch/x86/boot/vmlinux.bin

a arch/x86/boot/compressed/vmlinux je pouze běžný soubor 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 říká, že piggy.o je zdaleka největší soubor, takže jej hledáme a musí pocházet z:

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_ prefix vysvětlený níže.

arch/x86/boot/compressed/piggy.S obsahuje:

.incbin "arch/x86/boot/compressed/vmlinux.bin.gz"

viz také:https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc/36295692#36295692

arch/x86/boot/compressed/vmlinux.bin.gz pochází z:

cat arch/x86/boot/compressed/vmlinux.bin arch/x86/boot/compressed/vmlinux.relocs | \
gzip -n -f -9 > arch/x86/boot/compressed/vmlinux.bin.gz

který pochází z:

objcopy  -R .comment -S vmlinux arch/x86/boot/compressed/vmlinux.bin

který pochází z:

LD      vmlinux

což dělá:

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 je obrovský, ale všechny zobrazené objekty jsou podle ls -l malé , tak jsem prozkoumal a dozvěděl se o novém ar funkce, o které jsem nevěděl:tenké archivy.

V:

AR      built-in.a

sestava dělá:

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 určuje tenký archiv.

Pak můžeme vidět, že všechny dílčí archivy jsou také tenké, např. protože jsem upravil init/main.c , máme:

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

který nakonec pochází ze souboru C pomocí příkazu jako:

gcc \
-Wp,-MD,init/.main.o.d \
-c \
-o \
init/.tmp_main.o \
/work/linux-kernel-module-cheat/submodules/linux/init/main.c

Nemohu najít init/.tmp_main.o na init/main.o šlápnout na klády, což je škoda... s:

git grep '\.tmp_'

vidíme, že pravděpodobně pochází z scripts Makefile.build a je propojen s CONFIG_MODVERSIONS které jsem povolil:

ifndef CONFIG_MODVERSIONS
cmd_cc_o_c = $(CC) $(c_flags) -c -o [email protected] $<

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 [email protected] $(@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) [email protected];                  \
    fi;
endif

Analýza provedena s touto konfigurací, která obsahuje CONFIG_KERNEL_GZIP=y .

aarch64 arch/arm64/boot/Image

Pouze nekomprimovaný objcopy z vmlinux :

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

vmlinux se získává v podstatě úplně stejným způsobem jako pro x86 přes tenké archivy.

arch/arm/boot/zImage

Velmi podobné X86 se zazipovaným vmlinux , ale žádné kouzlo build.c krok. Shrnutí řetězce hovorů:

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 může bootovat z bzImage, ale ne vmlinux

Toto je další důležitý praktický rozdíl:https://superuser.com/questions/1451568/booting-an-uncompressed-kernel-in-qemu


Linux
  1. Jaký je rozdíl mezi #!/usr/bin/env bash a #!/usr/bin/bash?

  2. Jaký je rozdíl mezi fsck a e2fsck?

  3. Jaký je rozdíl mezi ovladači jádra a moduly jádra?

  1. Jaký je rozdíl mezi InnoDB a MyISAM?

  2. Jaký je rozdíl mezi `su -` a `su --login`?

  3. jaký je rozdíl mezi remount to umount/mount?

  1. Jaký je rozdíl mezi module_init a init_module v modulu jádra Linuxu?

  2. Jaký je rozdíl mezi strtok_r a strtok_s v C?

  3. Jaký je rozdíl mezi adduser a useradd?