刚刚接触到linux内核编译过程的时候,相信不少人跟我一样,都是按照手册或者网上的教程一步一步的执行,对于其中的很多原理和过程都是一知半解,这其中有一个很常见的问题,就是make image命令。

因为大家都知道,在编译linux内核时,往往会涉及到以下3个命令:

  • make Image
  • make zImage
  • make uImage

那么,这3个命令分别是做什么的?所生成的对象又有什么区别呢?

在网上查阅了很多的资料和博客,发现绝大部分都是千篇一律的说法,在对比上述3个概念的时候,顺带还对vmlinux、vmlinuz、initrd等诸多概念胡乱进行一通比较,概念模糊,根本没把问题解释清楚,很明显是互相摘抄、囫囵吞枣的。算了,还是我自己来捋一捋好了。

1、首先来解释一下前面2个命令的区别。Image为普通的内核映像文件,而zImage为压缩过的内核映像文件(其中的z字母就是压缩的意思)。一般情况下,编译出来的Image大约为4M,而zImage不到2M。

2、然后来解释一下第3个命令uImage。它是uboot专用的映像文件,它是在zImage之前加上一个长度为64字节的“头”,说明这个内核的版本、加载位置、生成时间、大小等信息;其0x40之后与zImage没区别。换句话说,如果直接从uImage的0x40位置开始执行,那么zImage和uImage没有任何区别。

为什么要用uboot 的mkimage工具处理内核映像zImage呢?

因为uboot在用bootm命令引导内核的时候,bootm需要读取一个64字节的文件头,来获取这个内核映象所针对的CPU体系结构、OS、加载到内存中的位置、在内存中入口点的位置以及映象名等等信息。这样bootm才能为OS设置好启动环境,并跳入内核映象的入口点。而mkimage就是添加这个文件头的专用工具。具体的实现请看uboot中bootm的源码和mkimage的源码。

3、另外,要额外说明的是如何来生成uImage。资料上显示,linux2.4之前版本的内核不支持直接生成uImage镜像文件,需要手动来生成。而对于linux2.6之后版本的内核,尽管加入了很多对嵌入式系统的支持,但是uImage的生成也需要单独设置。

那究竟要如何生成uImage呢?这就要从uboot处来想办法了。

uboot源代码的tools/目录下有一个mkimage工具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。

leon@Ubuntu:~/u-boot-2010.03/tools$ ls
bddb             fdt_ro.o        img2srec.o         mkimage.c
bin2header.c     fdt_rw.o        imls               mkimage.h
bmp_logo         fdt_strerror.o  imximage.c         mkimage.o
bmp_logo.c       fdt_wip.o       imximage.h         mpc86x_clk.c
bmp_logo.o       fit_image.c     imximage.o         ncb.c
crc32.o          fit_image.o     inca-swap-bytes.c  netconsole
default_image.c  gdb             jtagconsole        os_support.c
default_image.o  gen_eth_addr    kwbimage.c         os_support.h
easylogo         gen_eth_addr.c  kwbimage.h         os_support.o
env              gen_eth_addr.o  kwbimage.o         scripts
envcrc           getline.c       logos              setlocalversion
envcrc.c         getline.h       Makefile           sha1.o
envcrc.o         image.o         md5.o              ubsha1.c
env_embedded.o   img2brec.sh     mingw_support.c    updater
fdt_host.h       img2srec        mingw_support.h
fdt.o            img2srec.c      mkimageleon@Ubuntu:~/u-boot-2010.03/tools$ ll mkimage
-rwxrwxr-x 1 leon leon 62384  1月 26 22:30 mkimage*leon@Ubuntu:~/u-boot-2010.03/tools$ file mkimage
mkimage: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x366213ad60c7c7fc6793def77d2df59d2ab85d5d, stripped

下面介绍下mkimage这个工具的用法:

参数说明:

  • -A:指定 CPU 的体系结构,可用值有:alpha、arm 、x86、ia64、mips、mips64、 ppc 、s390、sh、sparc 、sparc64、m68k 等;
  • -O:指定操作系统类型,可用值有:openbsd、netbsd、freebsd、4_4bsd、linux、 svr4、esix、solaris、irix、sco、dell、ncr、lynxos、vxworks、psos、qnx、u-boot、rtems、artos;
  • -T:指定映象类型,可用值有:standalone、kernel、ramdisk、multi、firmware、script、filesystem;
  • -C:指定映象压缩方式,可用值有:
    :none 不压缩(一般使用这个,因为 zImage 是已经被 bzip2 压缩过的自解压内核);
    :zip 用 gzip 的压缩方式;
    :bzip2 用 bzip2 的压缩方式;
  • -a:指定映象在内存中的加载地址,映象下载到内存中时,要按照用 mkimage 制作映象 时,这个参数所指定的地址值来下载;
  • -e:指定映象运行的入口点地址,这个地址就是-a 参数指定的值加上 0x40(因为前面有个 mkimage 添加的 0x40 个字节的头);
  • -n:指定映象名;
  • -d:指定制作映象的源文件;

以下是我的示例(摘自tekkaman的制作内核映像的命令):

mkimage -n 'mykernel' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage.img

该命令的作用就是,将目录下的zImage文件制作成符合uboot引导要求的uImage.img文件,使得uboot能够正确的引导和启动linux内核。

其中有几点要注意:

1、关于偏移量的问题(请千万注意这一点)。’-e’命令之后的地址,必须比’-a’命令后的地址多0x40的偏移量。一旦没有偏移,则会导致系统出现引导失败的问题。而很多博客文章里,居然把这2个值写成一样的,都写成0x30008000。也不知道各位博主们自己到底有没有尝试过,害我一开始折腾了半天才发现这个问题,简直就是浪费我的时间。

**2、执行该命令时,要注意一下权限的问题。**我一开始时在虚拟机的共享目录下执行,一直提示失败:

leon@Ubuntu:/mnt/share/tmp/zImages$ mkimage -n 'mykernel' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage.img
mkimage: Can't map uImage.img: Invalid argument

后来跳转到~目录下执行,就一下子成功了。成功后的提示信息如下:

leon@Ubuntu:~$ mkimage -n 'mykernel' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage.img
Image Name:   mykernel
Created:      Wed Feb  1 14:50:47 2017
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    2266576 Bytes = 2213.45 kB = 2.16 MB
Load Address: 30008000
Entry Point:  30008040

将生成的image文件,拷贝到nfs目录下,按照uboot环境变量的预设名称改名,然后启动uboot,系统成功引导启动!

hit any key to stop auto_boot:  0
DM9000: Found at 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:08:11:18:12:27
Operating at 100M full duplex mode
Begin to Initiate NFS Process...
NFS Process Using dm9000 device
NFS: File transfer via NFS:Srver_Addr: 192.168.100.120;Local_Addr: 192.168.100.230;filename: '/opt/FriendlyARM/mini2440/rootfs/zImage.img'address: 0x30008000loading......
...........................................................................................................................................................................................................................................................................................................................................................................................................................................................done
Bytes transferred = 2266640 (229610 hex)
## Booting kernel from Legacy Image at 30008000 ...Image Name:   leon_20170201Created:      2017-02-01   6:50:47 UTCImage Type:   ARM Linux Kernel Image (uncompressed)Data Size:    2266576 Bytes =  2.2 MBLoad Address: 30008000Entry Point:  30008040Verifying Checksum ... OKXIP Kernel Image ... OK
OKStarting kernel ...
Uncompressing Linux................................................................................................................................................... done, booting the kernel.
Linux version 2.6.32.2-leon (leon@Ubuntu) (gcc version 4.4.3 (ctng-1.6.1) ) #1 Wed Feb 1 08:33:10 CST 2017
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache...(此处略去12345678个字).....NFS root ...Done

**3、将mkimage工具所在目录加入环境变量。**可以将mkimage这个工具拷贝到usr/bin等用户目录下,这样直接在命令行输入这个命令就可以运行,而无需每次都手工指定到uboot/tools这个目录下去,提高执行效率。当然,也可以按照我的另一篇博客(linux(ubuntu)编译linux内核提示"mkimage" command not found)中介绍的方案,直接在ubuntu系统中安装一下uboot的mkimage命令,效果更好。

**4、关于linux2.6之后版本的系统,是否可以直接make uImage?**这一点,虽然绝大部分的网文和博客中都说到要单独设置,但是却没有人明确指出要如何设置。我直接在ubuntu 12.04的系统(Linux Ubuntu 3.13.0-32-generic)中输入make uImage命令,确实能够运行,也确实在指定的目录下生成了uImage文件。

leon@Ubuntu:/opt/FriendlyARM/mini2440/linux-2.6.32.2$ make uImageCHK     include/linux/version.h
make[1]: “include/asm-arm/mach-types.h”是最新的。CHK     include/linux/utsrelease.hSYMLINK include/asm -> include/asm-armCALL    scripts/checksyscalls.shCHK     include/linux/compile.hKernel: arch/arm/boot/Image is readyKernel: arch/arm/boot/zImage is readyUIMAGE  arch/arm/boot/uImage
Image Name:   Linux-2.6.32.2-leon
Created:      Wed Feb  1 15:48:37 2017
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    2266576 Bytes = 2213.45 kB = 2.16 MB
Load Address: 30008000
Entry Point:  30008000
Image arch/arm/boot/uImage is ready

但是,遗憾的是,上面生成的镜像文件,导入到开发板上却无法执行!

hit any key to stop auto_boot:  0
DM9000: Found at 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:08:11:18:12:27
Operating at 100M full duplex mode
Begin to Initiate NFS Process...
NFS Process Using dm9000 device
NFS: File transfer via NFS:Srver_Addr: 192.168.100.120;Local_Addr: 192.168.100.230;filename: '/opt/FriendlyARM/mini2440/rootfs/zImage.img'address: 0x30008000loading......
..........................................T .................................................................................................................................................................................................................................................................................................................................................................................................................done
Bytes transferred = 2266640 (229610 hex)
## Booting kernel from Legacy Image at 30008000 ...Image Name:   Linux-2.6.32.2-leonCreated:      2017-02-01   7:48:37 UTCImage Type:   ARM Linux Kernel Image (uncompressed)Data Size:    2266576 Bytes =  2.2 MBLoad Address: 30008000Entry Point:  30008000Verifying Checksum ... OKXIP Kernel Image ... OK
OKStarting kernel ...         (卡在这里不动了............

至于失败的原因,我觉得很有可能就是因为没有配置参数,导致上述第一点中的偏移量没有设置进去。这一点,从上面的Load Address和Entry Point的值就可以看出来。待后续我查找到如何配置make uImage命令的参数时,再进行验证!

不管如何,今天总算是成功搞清楚了make zImage和make uImage命令的区别,也成功编译出了uImage镜像文件,并下载到mini2440开发板上利用nfs引导成功,算是比较满意的收获吧!

搞定,收工!

make zImage和make uImage的区别和mkimage工具的使用相关推荐

  1. 比较zImage和uImage的区别

    一.vmlinuz vmlinuz是可引导的.压缩的内核."vm"代表"Virtual Memory".Linux 支持虚拟内存,不像老的操作系统比如DOS有6 ...

  2. vmlinux、 Image, zImage、 uImage 的区别

    来自正点原子<[正点原子]I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf> vmlinux 是 ELF 格式的文件,但是在实际中我们不会使用 vmlinux,而是使用 zIm ...

  3. zImage与uImage的区别

    在编译Linux内核时,通常都是生成zImage, 它是一般情况下默认的压缩内核映像文件. 而实际上,zImage是通过压缩内核文件vmlinux后,再加上一段解压启动代码得到. 而uImage是u- ...

  4. mkimage工具将zImage转换为uImage

    正常引导的内核文件 [root@wtstb ~]# mount /dev/sda1 /mnt/ [root@wtstb ~]# file /mnt/hi_kernel.bin /mnt/hi_kern ...

  5. 2020.10.11--PS--矢量蒙版图层蒙版区别、文字工具、文字与路径

    矢量蒙版图层蒙版区别 矢量蒙板只能用矢量工具(钢笔.自由钢笔.矢量图形)来编辑,可以移动调节范围 图层蒙板通过像素来约束下面图层的显示和隐藏,可以通过像素工具(画笔,橡皮插等工具)画编辑. 文字工具 ...

  6. ps裁剪和裁切的区别_PS详细工具讲解剪切,裁剪的区别

    一.剪切 剪切,就是在当前图层建立好选区范围后,从该图层中剪掉选区中的元素. 比如就拿下列这张图举例,我们要把中间的那位红衣服的护士小姐姐给抠出来.就可以用剪切的方式. 具体方法如下: 点击套索工具( ...

  7. 如何修改uboot的环境变量env的值来指定uImage的名字

    今天继续玩基于uboot的nfs.昨天总算是基本搞清了make zImage和make uImage的区别,那么今天就来实际编译几个玩一玩. 不过,在利用mkimage工具对zImage镜像文件加工完 ...

  8. uImage和zImage的区别

    linux内核经过编译后会生成一个elf格式的可执行程序,叫vmlinux或vmlinuz,这个就是原始的未经任何处理加工的原版内核elf文件:嵌入式系统部署时烧录的一般不是这个vmlinuz/vml ...

  9. 嵌入式Linux中几种image的区别

    vmlinux 编译出来最原始的内核文件,未经压缩. zImage 由 vmlinux 经过 gzip 压缩而得. zImage 是由压缩后的 vmlinux 和解压缩程序组成. bzImage bz ...

最新文章

  1. Yahoo javascript 开源界面库YUI 和EXT
  2. forms身份验证 不跳转_“东湖24小时”玩不够?收好这份指南,365天不重样
  3. 双通输入法源码公布 by 尉迟方
  4. 最近任务-2012.05.14
  5. C# 房贷计算器(等本降息)
  6. TCP/IP数据包结构分析
  7. docker info 显示 Docker 系统信息
  8. ESP8266 建立TCPserver 进行数据互传
  9. 利用空余时间在完成一个Outlook框架控件,还有些Bug,完善中
  10. 在美国过端午节(诗)
  11. 转]python 结巴分词(jieba)学习
  12. 《软件构架实践》阅读笔记4
  13. 工科数学分析部分知识点整理
  14. 微分几何笔记(8) —— 切向量,切空间
  15. gitlab的账号注册以及分组
  16. 常识——手机当作无线网卡,通过usb与电脑共享网络,让电脑网卡支持5g网络
  17. android 闪屏动态界面,Android 实现闪屏
  18. 恒生电子(杭州、武汉、上海、、、)来实习来春招
  19. 微软关于dns配置的资料
  20. JDK1.8之前造成HashMap死链问题

热门文章

  1. ES6 Proxy兼容polyfill实现
  2. 利用python脚本(re)抓取美空mm图片
  3. bat批量删.svn
  4. TYVJ P1062 合并傻子 Label:环状dp
  5. An unspecified error occurred!
  6. Java程序猿JavaScript学习笔记(4——关闭/getter/setter)
  7. 开发工程师的职场人生路(转)
  8. html对字符串判空,使用XslCompiledTransform获取html作为字符串。结果为空
  9. 多个容器一起打包_容器快速入门完全指南
  10. 快速开发后台不用太多代码的 tp5_小程序·云开发优劣简述