博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内核 镜像 解析
阅读量:4286 次
发布时间:2019-05-27

本文共 8436 字,大约阅读时间需要 28 分钟。

前言
本文对编译 linux 生成的各种镜像进行解读
pc 一般用 bzImage ,并将其 命名 为 vmlinuz嵌入式 一般用 uImage , 也可以 用 Image
  • 各种镜像简介
最终编译结束,可能会生成多种内核镜像1. vmlinux  编译的时候make 工具读取.config文件,然后在顶层目录生成了vmlinux文件.vmlinux是未压缩的内核,vmlinuz是vmlinux的压缩文件。vmlinux 是ELF文件,即编译出的最原始的文件,或者称之为基本内核2. ImageImage是由内核顶层目录下的 vmlinux 二进制化后得到的ELF文件vmlinux经过objcopy后得到binary文件Image3. zImagelinux的作者们觉得Image还是太大了所以对Image进行了压缩,并且在image压缩后的文件的前端附加了一部分解压缩代码,构成了一个压缩格式的镜像就叫zImage。解压的时候,通过zImage镜像头部的解压缩代码进行自解压,然后执行解压出来的内核镜像。zImage的是elf格式的arch/arm/boot/compressed/vmlinux二进制化得到的zImage和bzImage是vmlinuz的存在形式,在x86系统中,我们是直接通过将bzImage拷贝为/boot/vmlinuz获得vmlinuz的。4. bzImagebzImage是压缩的内核映像,需要注意,bzImage不是用bzip2压缩 的,bzImage中的bz容易引起误解,bz表示“big zImage”。 bzImage中的b是“big”意思。 bzImage 是为了x86的 大内核(512kB)而作出的一种东西zImage(vmlinuz)和bzImage(vmlinuz)都是用gzip压缩的。5. vmlinuz (统称,不对应实物.包括 zImage 和 bzImage)vmlinuz(zImage或bzImage)Image 经过压缩后的文件。----10. uImageuboot为了启动linux内核,还发明了一种内核格式叫uImage。uImage是由zImage加工得到的,uboot中有一个工具,可以将zImage加工生成uImage。注意:uImage不关linux内核的事,linux内核只管生成zImage即可,然后uboot中的mkimage工具再去由zImage加工生成uImage来给uboot启动。这个加工过程其实就是在zImage前面加上64字节的uImage的头信息即可。---./vmlinux  				// 这个是没压缩的, 大小 83725768./arch/arm/boot/Image //大小 16864200./arch/arm/boot/compressed/vmlinux  // 这个是压缩过的 大小 7218420./arch/arm/boot/zImage // 大小 7128944./arch/arm/boot/uImage // 大小 7128944 + 64

各种镜像的生成过程(逆序)


uImage — arch/arm/boot/uImage

uImage 是由 一个脚本做出来的.

scripts/mkuboot.sh 脚本

整体的命令是scripts/mkuboot.sh -A arm -O linux -C none -T kernel -a 0x80008000 -e 0x80008000 -n 'Linux-3.10.0' -d arch/arm/boot/zImage arch/arm/boot/uImage命令解析:	-A arm 架构是arm	-O linux 系统是linux	-C none 没压缩	-T kernel 类型是kernel	-a 0x80008000 加载地址是0x80008000	-e 0x80008000 入口地址是0x80008000	-n 'Linux-3.10.0' 名字是Linux-3.10.0	-d arch/arm/boot/zImage 输入数据文件是arch/arm/boot/zImage	arch/arm/boot/uImage 输出文件是arch/arm/boot/uImage

scripts/mkuboot.sh 对mkimage命令进行判断是否存在,然后就调用了 mkimage $@,然后就制作出来了 arch/arm/boot/uImage , 把 选项中的参数 写到了uImage的前64字节,例如加载地址和入口地址


zImage — arch/arm/boot/zImage

uImage 是依靠mkimage命令 和 zImage 做出来的.命令可以在uboot源码tools目录编译得到,也可以直接安装得到.

下面看一下arch/arm/boot/zImage是怎么做出来的

他是由arch/arm/boot/compressed/vmlinux 二进制化得到的

arch/arm/boot/.zImage.cmd中写到

arm-hisiv300-linux-objcopy -O binary -R .comment -S  arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage命令解析:	-O binary 	输出目标为二进制文件	-R .comment 不拷贝.comment段	-S 					不拷贝重定位信息和符号信息到输出文件(目的文件)中去	arch/arm/boot/compressed/vmlinux 输入文件	arch/arm/boot/zImage 输出文件

vmlinux — arch/arm/boot/compressed/vmlinux

然后我们看一下arch/arm/boot/compressed/vmlinux 是怎么做出来的

arch/arm/boot/compressed/.vmlinux.cmd中写到

arm-hisiv300-linux-ld 	-EL  \  											--defsym _kernel_bss_size=138792 \  											--defsym zreladdr=0x80008000 \  											-p \  											--no-undefined \  											-X \  											-T arch/arm/boot/compressed/vmlinux.lds \  											arch/arm/boot/compressed/head.o arch/arm/boot/compressed/piggy.gzip.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\  											-o arch/arm/boot/compressed/vmlinux命令解析:	-EL 连接little-endian对象. 这会影响缺省输出格式	--defsym _kernel_bss_size=138792 在输出文件中定义一个全局变量 _kernel_bss_size 值为 138792	--defsym zreladdr=0x80008000 在输出文件中定义一个全局变量 zreladdr 值为 0x80008000	-p 动态库的问题	--no-undefined 好像是符号重定义的问题,不清楚	-X Delete all temporary local symbols	-T arch/arm/boot/compressed/vmlinux.lds 用arch/arm/boot/compressed/vmlinux.lds来替换默认链接脚本	arch/arm/boot/compressed/head.o 输入文件	-o arch/arm/boot/compressed/vmlinux 输出文件-rwxrwxr-x 1 linux linux 3.2M  4月 25 20:33 vmlinux*-rw-rw-r-- 1 linux linux 3.1M  4月 25 20:33 piggy.gzip.o

vmlinux — arch/arm/boot/compressed/vmlinux

  • 这个vmlinux是arch/arm/boot/compressed/中的vmlinux,注意区分文章后段中的vmlinux

vmlinux.lds是怎么做出来的? 没有命令的备份,打印信息里也没有,只能找Makefile了

arch/arm/boot/compressed/Makefile中写到

SEDFLAGS    = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG)    @sed "$(SEDFLAGS)" < $< > $@解析上面的命令,就是替换 vmlinux.lds.in 中的两个字符串,然后放入vmlinux.lds中.vmlinux.lds解析:ENTRY(_start) 表示,将符号_start设置成入口地址,入口地址(entry point)是指进程执行的第一条用户空间的指令在进程地址空间的地址SECTIONS{
. = 0; 把定位器符号置为0 _text = .; 将_text符号放在 0位置 .text : {
_start = .; 将_start符号放在0位置 *(.start) 将所有的输入文件的.start段放入输出文件的.text段 *(.text) 将所有的输入文件的.text段放入输出文件的.text段 *(.text.*) *(.fixup) *(.gnu.warning) *(.glue_7t) *(.glue_7) }}

我们之前看到

-rwxrwxr-x 1 linux linux 3.2M 4月 25 20:33 vmlinux
-rw-rw-r-- 1 linux linux 3.1M 4月 25 20:33 piggy.gzip.o
所以怀疑内核大部分在piggy.gzip.o文件中.


piggy.gzip.o

所以下面对piggy.gzip.o分析,根据 Makefile中 这一句$(obj)/piggy.$(suffix_y).o:  $(obj)/piggy.$(suffix_y) FORCE判 断,取决于piggy.gzip然后看下一句$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE    $(call if_changed,$(suffix_y))

很明显,这句就是说当依赖更新时,重新调用gzip命令,也就是将Image压缩成了piggy.gzip


Image — arch/arm/boot/Image

查看arch/arm/boot/.Image.cmd

arm-hisiv300-linux-objcopy -O binary -R .comment -S  vmlinux arch/arm/boot/Image命令解析:	-O binary 	输出目标为二进制文件	-R .comment 不拷贝.comment段	-S 					不拷贝重定位信息和符号信息到输出文件(目的文件)中去	vmlinux 顶层的vmlinux为输入文件	arch/arm/boot/Image 输出文件

vmlinux — 顶层vmlinux

  • 这个vmlinux是顶层的vmlinux,注意区分文章前段的vmlinux
    查看.vmlinux.cmd
/bin/bash scripts/link-vmlinux.sh arm-hisiv300-linux-ld -EL  -p --no-undefined -X --build-idscripts/link-vmlinux.sh解析首先用了下面这一个函数链接了vmlinux.omodpost_link(){
${
LD} ${
LDFLAGS} -r -o ${
1} ${
KBUILD_VMLINUX_INIT} \ --start-group ${
KBUILD_VMLINUX_MAIN} --end-group}然后用scripts/mod/modpost检查了vmlinux.o 并生成了Module.symvers${
MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o然后链接了init目录下的内容${
MAKE} -f "${srctree}/scripts/Makefile.build" obj=init然后就用到了执行了三次 kallsyms每次都是 vmlinux_link 生成一个文件,然后kallsyms使用这个文件,生成一个二进制文件.最后生成一个 kallsymso ,然后在用kallsymso生成vmlinux

vmlinux_link

vmlinux_link 解析

ld \-m elf_i386 --emit-relocs --build-id \-o $(2) \-T \arch/x86/kernel/head_32.o arch/x86/kernel/head32.o arch/x86/kernel/head.o init/built-in.o \--start-group usr/built-in.o arch/x86/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 test/built-in.o lib/lib.a arch/x86/lib/lib.a lib/built-in.o arch/x86/lib/built-in.o drivers/built-in.o sound/built-in.ofirmware/built-in.o arch/x86/pci/built-in.o arch/x86/power/built-in.oarch/x86/video/built-in.o net/built-in.o --end-group \$(1)

kallsysms

kallsyms解析


built-in.o

查看 init/.built-in.o.cmdarm-hisiv300-linux-ld -EL -r -o init/built-in.o init/main.o init/version.o init/mounts.o init/initramfs.o init/calibrate.o init/init_task.o 命令解析:	-EL 连接little-endian对象. 这会影响缺省输出格式	-r 产生可重定位的输出	-o init/built-in.o 输出文件	init/main.o init/version.o init/mounts.o init/initramfs.o init/calibrate.o init/init_task.o  出入文件其他目录下的built-in.o 也是这样子生成的.例如 fs 目录 前期在子目录下生成了fs/exofs/built-in.o文件,然后链接到了一起,生成了fs/fs/built-in.o 文件

uImage和zImage 的 具体区别

uIamge是由zImage 经工具mkimage制作而来的,制作的过程就是压缩

uboot目前只能支持uImage启动,不支持zImage启动
bootm加载linux镜像,加载的是uIamge,bootm需要先对uIamge解压,解压地址为内核入口地址。当解压完成时uIamge和zIamge几乎是相同的,差别是uImage比zImage多64字节

//多出的64字节2705 1956 fad0 6c19 58d0 99f5 0030 c5888000 8000 8000 8000 c959 2892 0502 02004c69 6e75 782d 332e 302e 3800 0000 00000000 0000 0000 0000 0000 0000 0000 0000// 这64字节对应的结构体 // u-boot-2017.05/include/image.htypedef struct image_header {
__be32 ih_magic; /* Image Header Magic Number */ __be32 ih_hcrc; /* Image Header CRC Checksum */ __be32 ih_time; /* Image Creation Timestamp */ __be32 ih_size; /* Image Data Size */ __be32 ih_load; /* Data Load Address */ __be32 ih_ep; /* Entry Point Address */ __be32 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;

参考资料

转载地址:http://gvigi.baihongyu.com/

你可能感兴趣的文章
DOM笔记(五):JavaScript的常见事件和Ajax小结
查看>>
DOM笔记(六):怎么进行JQuery扩展?
查看>>
搜索和网页排名的数学原理
查看>>
DOM笔记(八):JavaScript执行环境和垃圾收集
查看>>
响应式下的下拉菜单
查看>>
DOM笔记(九):引用类型、基本包装类型和单体内置对象
查看>>
也谈学习
查看>>
DOM笔记(十):JavaScript正则表达式
查看>>
如何高效编写可维护代码?
查看>>
DOM笔记(十一):JavaScript对象的基本认识和创建
查看>>
DOM笔记(十二):又谈原型对象
查看>>
DOM笔记(十三):JavaScript的继承方式
查看>>
CSS:响应式下的折叠菜单(条纹式)
查看>>
响应式设计三部曲
查看>>
45种Javascript技巧大全
查看>>
PDO学习笔记
查看>>
MarkDown语法
查看>>
Linux的文件权限
查看>>
全屏滚动实现:fullPage.js和fullPage
查看>>
SASS小结
查看>>