首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

zImage内核镜像解压过程详解 01

zImage内核镜像解压过程详解 01

 本文以linux-2.6.14内核在S3C2410平台上运行为例,讲解内核的解压过程。
  内核编译完成后会生成zImage内核镜像文件。关于bootloader加载zImage到内核,并且跳转到zImage开始地址运行zImage的过程,相信大家都很容易理解。但对于zImage是如何解压的过程,就不是那么好理解了。本文将结合部分关键代码,讲解zImage的解压过程。
  先看看zImage的组成吧。在内核编译完成后会在arch/arm/boot/下生成zImage。
  在arch/armboot/Makefile中:
  $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
  $(call if_changed,objcopy)
  由此可见,zImage的是elf格式的arch/arm/boot/compressed/vmlinux二进制化得到的
  在arch/armboot/compressed/Makefile中:
  $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o
  $(addprefix $(obj)/, $(OBJS)) FORCE
  $(call if_changed,ld)
  $(obj)/piggy.gz: $(obj)/../Image FORCE
  $(call if_changed,gzip)
  $(obj)/piggy.o: $(obj)/piggy.gz FORCE
  其中Image是由内核顶层目录下的vmlinux二进制化后得到的。注意:arch/arm/boot/compressed/vmlinux是位置无关的,这个有助于理解后面的代码。,链接选项中有个 –fpic参数:
  EXTRA_CFLAGS := -fpic
  总结一下zImage的组成,它是由一个压缩后的内核piggy.o,连接上一段初始化及解压功能的代码(head.o misc.o),组成的。
  下面就要看内核的启动了,那么内核是从什么地方开始运行的呢?这个当然要看lds文件啦。zImage的生成经历了两次大的链接过程:一次是顶层vmlinux的生成,由arch/arm/boot/vmlinux.lds(这个lds文件是由arch/arm/kernel/vmlinux.lds.S生成的)决定;另一次是arch/arm/boot/compressed/vmlinux的生成,是由arch/arm/boot/compressed/vmlinux.lds(这个lds文件是由arch/arm/boot/compressed/vmlinux.lds.in生成的)决定。zImage的入口点应该由arch/arm/boot/compressed/vmlinux.lds决定。从中可以看出入口点为‘_start’
  OUTPUT_ARCH(arm)
  ENTRY(_start)
  SECTIONS
  {
  . = 0;
  _text = .;
  .text : {
  _start = .;
  *(.start)
  *(.text)
  ……
  }
  在arch/arm/boot/compressed/head.S中找到入口点。
  看看head.S会做些什么样的工作:
   对于各种arm CPU的DEBUG输出设定,通过定义宏来统一操作;
  设置kernel开始和结束地址,保存architecture ID;
   如果在arm2以上的CPU中,用的是普通用户模式,则升到超级用户模式,然后关中断
   分析LC0结构delta offset,判断是否需要重载内核地址(r0存入偏移量,判断r0是否为零)。
  需要重载内核地址,将r0的偏移量加到BSS region和GOT table中的每一项。
  对于位置无关的代码,程序是通过GOT表访问全局数据目标的,也就是说GOT表中中记录的是全局数据目标的绝对地址,所以其中的每一项也需要重载。
   清空bss堆栈空间r2-r3
返回列表