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之间的异同
编译过RedHat Linux内核的人对其中的System.map、vmlinuz、initrd-2.4.7-10.img印象可能比较深刻,因为编译内核过程中涉及到这些文件的建立等操作。那么这几个文件是怎么产生的?又有什么作用呢?本文对此做些介绍。
此外,平时调试用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