vmlinux, zImage, Image的區別


Copy from :https://blog.csdn.net/pi408637535/article/details/38438309

 

一、Linux內核鏡像格式  
   Linux內核有多種格式的鏡像,包括vmlinux、Image、zImage、bzImage、uImage、xipImage、bootpImage等.
(1)kernel鏡像格式:vmlinux
   vmlinuz是可引導的、可壓縮的內核鏡像,vm代表Virtual Memory.Linux支持虛擬內存,因此得名vm.它是由用戶對內核源碼編譯得到,實質是elf格式的文件.也就是說,vmlinux是編譯出來的最原始的內核文件,未壓縮.這種格式的鏡像文件多存放在PC機上.
  【 attention】elf格式文件
      ELF,Executable and Linkable  Format,可執行可鏈接格式,是UNIX實驗室作為應用程序二進制接口而發布的,擴展名為elf.可以簡單的認為,在elf格式的文件中,除二進制代 碼外,還包括該可執行文件的某些信息,比如符號表等.
(2)kernel鏡像格式:Image
   Image是經過objcopy處理的只包含二進制數據的內核代碼,它已經不是elf格式了,但這種格式的內核鏡像還沒有經過壓縮.
  【 attention】objcopy
       GNU使用工具程序objcopy作用是拷貝一個目標文件的內容到另一個目標文件中,也就是說,可以將一種格式的目標文件轉換成另一種格式的目標文件. 通過使用binary作為輸出目標(-o  binary),可產生一個原始的二進制文件,實質上是將所有的符號和重定位信息都將被拋棄,只剩下二進制數據.
(3)kernel鏡像格式:zImage
   zImage是ARM linux常用的一種壓縮鏡像文件,它是由vmlinux加上解壓代碼經gzip壓縮而成,命令格式是#make zImage.這種格式的Linux鏡像文件多存放在NAND上.
(4)kernel鏡像格式:bzImage
   bz表示big zImage,其格式與zImage類似,但采用了不同的壓縮算法,注意,bzImage的壓縮率更高.
(5)kernel鏡像格式:uImage
    uImage是uboot專用的鏡像文件,它是在zImage之前加上一個長度為0x40的頭信息(tag),在頭信息內說明了該鏡像文件的類型、加載 位置、生成時間、大小等信息.換句話說,若直接從uImage的0x40位置開始執行,則zImage和uImage沒有任何區別.命令格式是#make  uImage.這種格式的Linux鏡像文件多存放在NAND上.
(6)kernel鏡像格式:xipImage
   這種格式的Linux鏡像文件多存放在NorFlash上,且運行時不需要拷貝到內存SDRAM中,可以直接在NorFlash中運行.


二、Linux內核鏡像的產生過程
  在嵌入式Linux中,內核的啟動過程分為兩個階段.其中,第一階段啟動代碼放在arch/arm/kernel/head.S文件中,該文件與體系 結果相關,與用戶的開發板無關,主要是初始化ARM內核等.第二階段啟動代碼是init目錄下的main.c.現以執行命令#make  zImage為例來說明,arm-linux內核鏡像的產生過程.
(1)當用戶對Linux內核源碼進行編譯時,kernel的第1/2階段代碼會生成可執行文件vmlinux,該文件是未被壓縮的鏡像文件,非常大,不能直接下載到NAND中,通常放在PC機上,這也是最原始的Linux鏡像文件.試驗時該文件約50M.
(2)鏡像文件vmlinux由於很大,肯定不能直接燒入NAND中,因此需要進行二進制化,即經過objcopy處理,使之只包含二進制數據的內核代 碼,去除不需要的文件信息等,這樣就制作成了image鏡像文件.該鏡像文件也是未壓縮,只是經過了二進制化而變小.試驗時該文件約5M.
(3)  一般來說,內存SDRAM中的內核鏡像是經過壓縮的,只是在運行時再將其解壓.所以,編譯時會先使用gzip將鏡像文件image進行壓縮(壓縮比約為  2:1),再將壓縮后的鏡像文件和源碼中的兩個文件arch/arm/boot/compressed/head.S、arch/arm/boot  /compressed/misc.c一起鏈接生成壓縮后的鏡像文件compress/vmlinux.試驗時該文件約為2.5M.注意,這兩個源碼文件 是解壓程序,用於將內存SDRAM中的壓縮鏡像zImage進行解壓.
(4)壓縮后的鏡像文件compress/vmlinux經過二進制化,最終生成鏡像文件zImage,試驗時該文件約為2.5M.當然,在內存 SDRAM中運行壓縮鏡像文件zImage時,會首先調用兩個解壓程序arch/arm  /boot/compressed/head.S、arch/arm/boot/compressed/misc.c將自身解壓,然后再執行kernel   的第一階段啟動代碼arch/arm/kernel/head.S.簡而言之,在內存中運行內核時,kernel先自身解壓,再執行第一階段啟動代碼.試 驗時運行在內存中的鏡像文件約為5M,與image鏡像文件大小相同.
【 attention】
(1) 網站: http://lxr.linux.no/
   該網站通過了Linux內核源碼,不用解壓,在線查詢,非常方便.
(2)生成的鏡像文件vmlinux放在源碼的頂層目錄下.
(3)生成的鏡像文件image、zImage均在arch/arm/boot目錄下.
(4)啟動開發板時,在超級終端內會有許多的提示信息,其中:
      booting linux ...  /*表示正在將內核從NAND拷貝到內存中*/
      unpressed...      /*表示正在解壓內核*/
(5)只有當用戶輸入boot命令或在boot_delay延時時間后,vivi才將NANDFlash中的內核kernel拷貝到內存SDRAM中.也就是說,當vivi進入命令行模式時,在SDRAM中並沒有內核kernel.
(6)在kernel源碼目錄下執行命令:
  <1> #tree       /*打印出kernel源碼的目錄結構*/
  <2> #tree -L 1   /*打印出kernel源碼的第一級目錄結構*/
  <3> #tree > /home/lishuai/linux.txt   /*將kernel源碼的目錄結構重定向到某個文件中,用戶可以隨時查看其目錄結構,非常方便*/

 

 

 

 

 

  
  LD      vmlinux
  SYSMAP  System.map
  SYSMAP  .tmp_System.map
  OBJCOPY arch/arm/boot/Image
  Kernel: arch/arm/boot/Image is ready
  AS      arch/arm/boot/compressed/head.o
  GZIP    arch/arm/boot/compressed/piggy.gz
  AS      arch/arm/boot/compressed/piggy.o
  CC      arch/arm/boot/compressed/misc.o
  AS      arch/arm/boot/compressed/head-xscale.o
  LD      arch/arm/boot/compressed/vmlinux
  OBJCOPY arch/arm/boot/zImage

vmlinux 是一個elf格式的文件
       Image 是經過objcopy 處理了的只包含內核代碼,數據的一個文件, 已經不是elf格式的了。此時還沒有經過壓縮
arch/arm/boot/compressed/vmlinux 是經過壓縮的Image和加入了解壓頭的elf格式的文件
arch/arm/boot/zImage 是經過objcopy處理了的可以直接下到對應的地址執行的內核鏡像

objcopy:

GNU實用工具程序objcopy的作用是拷貝一個目標文件的內容到另一個目標文件中。 Objcopy使用GNU  BFD庫去讀或寫目標文件。Objcopy可以使用不同於源目標文件的格式來寫目的目標文件(也即是說可以將一種格式的目標文件轉換成另一種格式的目標文 件)。通過以上命令行選項可以控制Objcopy的具體操作。

Objcopy在進行目標文件的轉換時,將生成一個臨時文件,轉換完成后就將這個臨時文件刪掉。Objcopy使用BFD做轉換工作。如果沒有明確 地格式要求,則Objcopy將訪問所有在BFD庫中已經描述了的並且它可以識別的格式,請參見《GNUpro Decelopment  Tools》中“using ld”一章中“BFD庫”部分和“BFD庫中規范的目標文件格式”部分。

通過使用srec作為輸出目標(使用命令行選項-o srec),Objcopy可以產生S記錄格式文件。

通過使用binary作為輸出目標(使用命令行選項-o  binary),Objcopy可以產生原始的二進制文件。使用Objcopy產生一個原始的二進制文件,實質上是進行了一回輸入目標文件內容的內存轉 儲。所有的符號和重定位信息都將被丟棄。內存轉儲起始於輸入目標文件中那些將要拷貝到輸出目標文件去的部分的最小虛地址處。

使用Objcopy生成S記錄格式文件或者原始的二進制文件的過程中,-S選項和-R選項可能會比較有用。-S選項是用來刪掉包含調試信息的部分,-R選項是用來刪掉包含了二進制文件不需要的內容的那些部分。 

vmlinux,vmlinuz,uImage,zImage,bzImage之間的異同  

       在網絡中,不少服務器采用的是Linux系統。為了進一步提高服務器的性能,可能需要根據特定的硬件及需求重新編譯Linux內 核。編譯 Linux 內核,需要根據規定的步驟進行,編譯內核過程中涉及到幾個重要的文件。比如對於RedHat  Linux,在/boot目錄下有一些與Linux內核有關的文件,進入/boot執行。 
  編譯過RedHat Linux內核的人對其中的System.map、vmlinuz、initrd-2.4.7-10.img印象可能比較深刻,因為編譯內核過程中涉及到這些文件的建立等操作。那么這幾個文件是怎么產生的?又有什么作用呢?本文對此做些介紹。
  一、vmlinuz
  vmlinuz是可引導的、壓縮的內核。“vm”代表“Virtual Memory”。Linux  支持虛擬內存,不像老的操作系統比如DOS有640KB內存的限制。Linux能夠使用硬盤空間作為虛擬內存,因此得名“vm”。vmlinuz是可執行 的Linux內核,它位於/boot/vmlinuz,它一般是一個軟鏈接,比如圖中是vmlinuz-2.4.7-10的軟鏈接。
  vmlinuz的建立有兩種方式。一是編譯內核時通過“make zImage”創建,手動拷貝到/boot目錄下面。zImage適用於小內核的情況,它的存在是為了向后的兼容性。
  二是內核編譯時通過命令make  bzImage創建,然后手動拷貝至/boot目錄下。bzImage是壓縮的內核映像,需要注意,bzImage不是用bzip2壓縮的,  bzImage中的bz容易引起誤解,bz表示“big zImage”。 bzImage中的b是“big”意思。  zImage(vmlinuz)和bzImage(vmlinuz)都是用gzip壓縮的。它們不僅是一個壓縮文件,而且在這兩個文件的開頭部分內嵌有  gzip解壓縮代碼。所以你不能用gunzip 或 gzip –dc解包vmlinuz。
  內核文件中包含一個微型的gzip用於解壓縮內核並引導它。兩者的不同之處在於,老的zImage解壓縮內核到低端內存(第一個  640K),bzImage解壓縮內核到高端內存(1M以上)。如果內核比較小,那么可以采用zImage或bzImage之一,兩種方式引導的系統運行 時是相同的。大的內核采用bzImage,不能采用zImage。vmlinux是未壓縮的內核,vmlinuz是vmlinux的壓縮文件。
  二、initrd-x.x.x.img
  initrd是“initial ramdisk”的簡寫。initrd一般被用來臨時的引導硬件到實際內核vmlinuz能夠接管並繼續引導的狀態。圖中的initrd-2.4.7-10.img主要是用於加載ext3等文件系統及scsi設備的驅動。
  比如,使用的是scsi硬盤,而內核vmlinuz中並沒有這個scsi硬件的驅動,那么在裝入scsi模塊之前,內核不能加載根文件系 統,但  scsi模塊存儲在根文件系統的/lib/modules下。為了解決這個問題,可以引導一個能夠讀實際內核的initrd內核並用initrd修正  scsi引導問題。initrd-2.4.7-10.img是用gzip壓縮的文件,initrd實現加載一些模塊和安裝文件系統等功能。
  initrd映象文件是使用mkinitrd創建的。mkinitrd實用程序能夠創建initrd映象文件。這個命令是RedHat專有的(這也是為什么,在Linux內核包里/Documentation/Changes里面沒有提到要將mkinitrd升級)。其它Linux發行版或許有相應的命令。這是個很方便的實用程序。具體情況請看幫助:man mkinitrd下面的命令創建initrd映象文件。
   三、uImage文件
  vmlinux是內核文件,zImage是一般情況下默認的壓縮內核映像文件,壓縮vmlinux,加上一段解壓啟動代碼得到。而  uImage則是使用工具mkimage對普通的壓縮內核映像文件(zImage)加工而得。它是uboot專用的映像文件,它是在zImage之前加上 一個長度為64字節的“頭”,說明這個內核的版本、加載位置、生成時間、大小等信息;其0x40之后與zImage沒區別。 
其實就是一個自動跟手動的區別,有了uImage頭部的描述,u-boot就知道對應Image的信息,如果沒有頭部則需要自己手動去搞那些參數。
如何生成  uImage文件?首先在uboot的/tools目錄下尋找mkimage文件,把其copy到系統/usr/local/bin目錄下,這樣就完成制 作工具。然后在內核目錄下運行make uImage,如果成功,便可以在arch/arm/boot/目錄下發現uImage文件,其大小比  zImage多64個字節。

此外,平時調試用uImage,不用去管調整了哪些東西;zImage則是一切OK后直接燒0X0。開機就運行。

 在make install發生的事

在make install后, 會有三個文件被放到/boot下:
1. vmlinuz-2.6.x.y.z
2. System.map
3. config
4. 為什么我的gentoo沒有initrd.img的??
在/usr/src/linux下還有一個vmlinux的方件.

 那么/boot下的vmlinux是哪個呢? 如下:

jessinio@niolaptop /usr/src/linux $ diff /usr/src/linux/arch/x86/boot/bzImage /usr/src/linux/vmlinux
Files /usr/src/linux/arch/x86/boot/bzImage and /usr/src/linux/vmlinux differ
jessinio@niolaptop /usr/src/linux $ diff /usr/src/linux/arch/x86/boot/bzImage /boot/vmlinuz

可以看出/boot下的vmlinux是/usr/src/linux/arch/x86/boot/bzImage


隨便提一下make內核時的過程:

就常使用的make也過程:
cd /usr/src/linux
make menuconfig
make
make modules_install
make install

注意到上面的一個make是不參數的, 這種情況實際如下:
Execute "make" or "make all" to build all targets marked with [*]

帶"*"號等於如下:
make vlinux modules bzImage

 zImage / vmlinux / Image生成的流程圖

 SRC_TREE    :=./
HEADER_PATH    :=arch/arm/boot/compressed
BOOT_PATH    :=arch/arm/boot/
KERNEL_PATH    :=arch/arm/kernel

-----------------------------------------------------------------------------------------------------------------------

1 SRC_TREE 目錄下的vmlinux經過objcoy后生成二進制文件Image,Image在經過gzip壓縮后生成piggy.o
   piggy.o是真正的內核鏡像文件

2 HEADER_PATH/head.o ,head-xscal.o ,misc.o 的作用就是把piggy.o解壓到指定的位置,然后執行piggy.o解壓后的代碼


HEADER_PATH/zImage
       ^
       |[objcopy]
       |
HEADER_PATH/vmlinux
       ^
       |[ld]
       |
       +-<--HEADER_PATH/head.o
       |
       +-<--HEADER_PATH/head-xscal.o
       |
       +-<--HEADER_PATH/misc.o
       |
       +-<--HEADER_PATH/piggy.o <-- HEADER_PATH/piggy.gz <--[gzip]-- BOOT_PATH/Image <--[objcopy]--SRC_TREE/vmlinux

-----------------------------------------------------------------------------------------------------------------------
SRC_TREE目錄下的vmlinux是由一下三部分組成的:

$(vmlinux-init)

$(vmlinux-main)

kallsyms.o

vmlinux
   ^
   |
   +-<--$(vmlinux-init)
   |          ^
   |          |
   |          +--<--KERNEL_PATH/head.S
   |          |
   |          +--<--KERNEL_PATH/init_task.o
   |          |
   |          +--<--SRC_TREE/init/build-in.o
   |         
   +--< $(vmlinux-main)
   |          ^
   |          |$(cory-y)
   |          +--<--SRC_TREE/driver/built-in.o
   |          |
   |          +--<--SRC_TREE/mm/built-in.o
   |          |
   |          +--<--SRC_TREE/usr/built-in.o
   |          |
   |          +--<--SRC_TREE/kernel/built-in.o
   |          |
   |          +--<--SRC_TREE/mm/built-in.o
   |          |
   |          +--<--SRC_TREE/fs/built-in.o
   |          |
   |          +--<--SRC_TREE/ipc/built-in.o
   |          |
   |          +--<--SRC_TREE/securiy/built-in.o
   |          |
   |          +--<--SRC_TREE/crypto/built-in.o
   |          |
   |          +--<--SRC_TREE/block/built-in.o
   |          |
   |          +--<--arch/arm/kernel/built-in.o
   |          |
   |          +--<--arch/arm/mm/built-in.o
   |          |
   |          +--<--arch/arm/common/built-in.o 
   |          |
   |          +--<--arch/arm/mach-pxa/built-in.o
   |          |
   |          +--<--arch/arm/nwfpe/buit-in.o
   |          |
   |          |$(lib-y)
   |          +--<--SRC_TREE/lib/built-in.o 
   |          |
   |          +--<--arch/arm/lib/built-in.o
   |          |
   |          |$(drivers-y)
   |          +--<--SRC_TREE/drivers/buit-in.o 
   |          |
   |          +--<--SRC_TREE/sound/buit-in.o
   |          |
   |          |$(net-y)
   |          +--<--SRC_TREE/net/buit-in.o
   |
   +--< kallsyms.o

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM