vmlinux,vmlinuz,bzimage,zimage,initrd.img uimage的區別與聯繫

1.vmlinux

     vmlinux是未壓縮的內核, vmlinux 是ELF文件,即編譯出來的最原始的文件。用於kernel-debug,產生system.map符號表,不能用於直接加載,不可以作爲啓動內核。只是啓動過程中的中間媒體。 vmlinux.bin  The same as vmlinux, but in a binary file format.

vmlinux的獲得

vmlinux是Linux源碼編譯後未壓縮的內核,我們查看源碼根目錄下的.vmlinux.cmd文件,可以看到:

cmd_vmlinux := ld -m elf_i386 -m elf_i386 -o vmlinux -T arch/i386/kernel/vmlinux.lds arch/i386/kernel/head.o arch/i386/kernel/init_task.o init/built-in.o --start-group usr/built-in.o arch/i386/kernel/built-in.o arch/i386/mm/built-in.o arch/i386/mach-default/built-in.o arch/i386/crypto/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 lib/lib.a arch/i386/lib/lib.a lib/built-in.o arch/i386/lib/built-in.o drivers/built-in.o sound/built-in.o arch/i386/pci/built-in.o net/built-in.o --end-group .tmp_kallsyms2.o

這說明vmlinux是由arch/i386/kernel/head.o和arch/i386/kernel /init_task.o以及各個相關子目錄下的built-in.o鏈接而成的。注意按照鏈接順序我們可以發現arch/i386/kernel /head.S的目標文件似乎比較靠前。


2.vmlinuz

      vmlinuz是可引導的、壓縮的內核。“vm”代表“Virtual Memory”。Linux 支持虛擬內存,不像老的操作系統比如DOS有640KB內存的限制。Linux能夠使用硬盤空間作爲虛擬內存,因此得名“vm”。vmlinuz是可執行的Linux內核,它位於/boot/vmlinuz,它一般是一個軟鏈接。但是,它已經丟失了調試信息等,不可用於調試,這就是爲什麼perf和systemtap等內核級別的調試軟件安裝的時候,需要重新編譯內核的原因。同理,解壓縮vmlinuz是不能得到Vmlinux的。相對於vmlinux,它增加了解壓縮和boot的部分 

3.zimage

     zImage是vmlinuz經過gzip壓縮後的文件,適用於小內核(512KB以內),加載到內存的開始640KB處。

4.bzimage(not bzizp but big)

      bzImage是vmlinuz經過gzip壓縮後的文件,適用於大內核。爲什麼會發明bzimage這種內核鏡像呢?隨着linux內核的成熟,linux內核大小逐漸增大,超過了一些體系結構的限制,導致存儲壓縮內核的空間受到限制。bzimage這種格式就是爲了克服這種限制,它通過把kernel分解到不相鄰的內存區域來達到這一個目的。 

bzimage包含以下目標文件  bootsect.o  +  setup.o  +  misc.o  +  piggy.o .

bootsect:這個程序是linuxkernel的第一個程序,包括了linux自己的bootstrap程序,主要進行開機後加載真正內核鏡像之前的各種準備工作.注意它是用來load bzimage,不是bzimage的一部分(這句話存在質疑)。 

setup:進行實模式設置  misc:        piggy.o  包含被壓縮的vmlinux 

bzimage的解剖圖:

bzImage的獲得

bzImage是內核的壓縮版本,一般可以是vmlinux大小的三分之一左右。

首先查看生成bzImage的鏈接文件arch/i386/boot/.bzImage.cmd

cmd_arch/i386/boot/bzImage := arch/i386/boot/tools/build -b arch/i386/boot/bootsect arch/i386/boot/setup arch/i386/boot/vmlinux.bin CURRENT > arch/i386/boot/bzImage

接下去根據線索我們查看生成vmlinux.bin的鏈接文件arch/i386/boot/.vmlinux.bin.cmd

cmd_arch/i386/boot/vmlinux.bin := objcopy -O binary -R .note -R .comment -S arch/i386/boot/compressed/vmlinux arch/i386/boot/vmlinux.bin

然後查看生成vmlinux的鏈接文件arch/i386/boot/compressed/.vmlinux.cmd

cmd_arch/i386/boot/compressed/vmlinux := ld -m elf_i386 -m elf_i386 -T arch/i386/boot/compressed/vmlinux.lds arch/i386/boot/compressed/head.o arch/i386/boot/compressed/misc.o arch/i386/boot/compressed/piggy.o -o arch/i386/boot/compressed/vmlinux

接下去查看生成piggy.o的鏈接文件arch/i386/boot/compressed/.piggy.o.cmd

cmd_arch/i386/boot/compressed/piggy.o := ld -m elf_i386 -m elf_i386 -r --format binary --oformat elf32-i386 -T arch/i386/boot/compressed/vmlinux.scr arch/i386/boot/compressed/vmlinux.bin.gz -o arch/i386/boot/compressed/piggy.o

然後接下去查看生成vmlinux.bin.gz的鏈接文件arch/i386/boot/compressed/.vmlinux.bin.gz.cmd

cmd_arch/i386/boot/compressed/vmlinux.bin.gz := gzip -f -9 < arch/i386/boot/compressed/vmlinux.bin > arch/i386/boot/compressed/vmlinux.bin.gz

最後我們查看生成vmlinux.bin的鏈接文件arch/i386/boot/compressed/.vmlinux.bin.cmd,注意這裏的vmlinux就是根目錄下的vmlinux。

cmd_arch/i386/boot/compressed/vmlinux.bin := objcopy -O binary -R .note -R .comment -S vmlinux arch/i386/boot/compressed/vmlinux.bin

下面我們將生成bzImage的過程總結一下:

a。由vmlinux文件strip掉符號表得到arch/i386/boot/compressed/vmlinux.bin

b。將vmlinux.bin壓縮成vmlinux.bin.gz

c。將vmlinux.scr和vmlinux.bin.gz鏈接成piggy.o

d。將head.o、misc.o和piggy.o鏈接成當前目錄下的vmlinux

e。將vmlinux文件strip掉符號表得到arch/i386/boot/vmlinux.bin

f。將bootsect、setup和vmlinux.bin拼接成bzImage

5. uImage         

  uboot專用的內核鏡像,在zImage前加了一個64字節的頭,描述內核版本、加載地址生成時間,文件大小等等。 其0x40後的內容和zImage一樣。它是由uboot的工具mkImage生成的。

mkimage是在製作鏡像文件時候, 在原來的image文件前增加一個0x40字節長度的頭,增加的頭結構描述如下

/*
 * Legacy format image header,
 * all data in network byte order (aka natural aka bigendian).
 */
typedef struct image_header {
    uint32_t    ih_magic;   /* Image Header Magic Number    */
    uint32_t    ih_hcrc;    /* Image Header CRC Checksum    */
    uint32_t    ih_time;    /* Image Creation Timestamp */
    uint32_t    ih_size;    /* Image Data Size      */
    uint32_t    ih_load;    /* Data  Load  Address      */
    uint32_t    ih_ep;      /* Entry Point Address      */
    uint32_t    ih_dcrc;    /* Image Data CRC Checksum  */
    uint8_t     ih_os;      /* Operating System     */
    uint8_t     ih_arch;    /* CPU architecture     */
    uint8_t     ih_type;    /* Image Type           */
    uint8_t     ih_comp;    /* Compression Type     */
    uint8_t     ih_name[IH_NMLEN];  /* Image Name       */
} image_header_t;

Image Name佔用了32字節,其他信息佔用了32字節

mkimage用法:

Usage: ./mkimage -l image
          -l ==> list image header information
       ./mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
          -A ==> set architecture to 'arch'
          -O ==> set operating system to 'os'
          -T ==> set image type to 'type'
          -C ==> set compression type 'comp'
          -a ==> set load address to 'addr' (hex)
          -e ==> set entry point to 'ep' (hex)
          -n ==> set image name to 'name'
          -d ==> use image data from 'datafile'
          -x ==> set XIP (execute in place)
       ./mkimage [-D dtc_options] -f fit-image.its fit-image

-A 設定架構類型,可取值參照uboot/common/image.c

-O 設定操作系統類型,可取值參照uboot/common/image.c

-T image類型,可取值參照uboot/common/image.c

-a 指定image在內存中的加載地址

-e 指定image運行的入口點地址

-C 指定壓縮方式,壓縮方式參考uboot/common/image.c

-d data_file[:data_file...] 製作image的源文件

示例

 $MKIMAGE_TOOL -A arm -O linux -T kernel -C none -a 0x90008000 -e 0x90008000 -n "Android Linux Kernel" -d ./zImage  ./uImage


發佈了11 篇原創文章 · 獲贊 10 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章