make zImage和make uImage的区别和mkimage工具的使用
刚刚接触到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工具的使用相关推荐
- 比较zImage和uImage的区别
一.vmlinuz vmlinuz是可引导的.压缩的内核."vm"代表"Virtual Memory".Linux 支持虚拟内存,不像老的操作系统比如DOS有6 ...
- vmlinux、 Image, zImage、 uImage 的区别
来自正点原子<[正点原子]I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf> vmlinux 是 ELF 格式的文件,但是在实际中我们不会使用 vmlinux,而是使用 zIm ...
- zImage与uImage的区别
在编译Linux内核时,通常都是生成zImage, 它是一般情况下默认的压缩内核映像文件. 而实际上,zImage是通过压缩内核文件vmlinux后,再加上一段解压启动代码得到. 而uImage是u- ...
- mkimage工具将zImage转换为uImage
正常引导的内核文件 [root@wtstb ~]# mount /dev/sda1 /mnt/ [root@wtstb ~]# file /mnt/hi_kernel.bin /mnt/hi_kern ...
- 2020.10.11--PS--矢量蒙版图层蒙版区别、文字工具、文字与路径
矢量蒙版图层蒙版区别 矢量蒙板只能用矢量工具(钢笔.自由钢笔.矢量图形)来编辑,可以移动调节范围 图层蒙板通过像素来约束下面图层的显示和隐藏,可以通过像素工具(画笔,橡皮插等工具)画编辑. 文字工具 ...
- ps裁剪和裁切的区别_PS详细工具讲解剪切,裁剪的区别
一.剪切 剪切,就是在当前图层建立好选区范围后,从该图层中剪掉选区中的元素. 比如就拿下列这张图举例,我们要把中间的那位红衣服的护士小姐姐给抠出来.就可以用剪切的方式. 具体方法如下: 点击套索工具( ...
- 如何修改uboot的环境变量env的值来指定uImage的名字
今天继续玩基于uboot的nfs.昨天总算是基本搞清了make zImage和make uImage的区别,那么今天就来实际编译几个玩一玩. 不过,在利用mkimage工具对zImage镜像文件加工完 ...
- uImage和zImage的区别
linux内核经过编译后会生成一个elf格式的可执行程序,叫vmlinux或vmlinuz,这个就是原始的未经任何处理加工的原版内核elf文件:嵌入式系统部署时烧录的一般不是这个vmlinuz/vml ...
- 嵌入式Linux中几种image的区别
vmlinux 编译出来最原始的内核文件,未经压缩. zImage 由 vmlinux 经过 gzip 压缩而得. zImage 是由压缩后的 vmlinux 和解压缩程序组成. bzImage bz ...
最新文章
- Yahoo javascript 开源界面库YUI 和EXT
- forms身份验证 不跳转_“东湖24小时”玩不够?收好这份指南,365天不重样
- 双通输入法源码公布 by 尉迟方
- 最近任务-2012.05.14
- C# 房贷计算器(等本降息)
- TCP/IP数据包结构分析
- docker info 显示 Docker 系统信息
- ESP8266 建立TCPserver 进行数据互传
- 利用空余时间在完成一个Outlook框架控件,还有些Bug,完善中
- 在美国过端午节(诗)
- 转]python 结巴分词(jieba)学习
- 《软件构架实践》阅读笔记4
- 工科数学分析部分知识点整理
- 微分几何笔记(8) —— 切向量,切空间
- gitlab的账号注册以及分组
- 常识——手机当作无线网卡,通过usb与电脑共享网络,让电脑网卡支持5g网络
- android 闪屏动态界面,Android 实现闪屏
- 恒生电子(杭州、武汉、上海、、、)来实习来春招
- 微软关于dns配置的资料
- JDK1.8之前造成HashMap死链问题
热门文章
- ES6 Proxy兼容polyfill实现
- 利用python脚本(re)抓取美空mm图片
- bat批量删.svn
- TYVJ P1062 合并傻子 Label:环状dp
- An unspecified error occurred!
- Java程序猿JavaScript学习笔记(4——关闭/getter/setter)
- 开发工程师的职场人生路(转)
- html对字符串判空,使用XslCompiledTransform获取html作为字符串。结果为空
- 多个容器一起打包_容器快速入门完全指南
- 快速开发后台不用太多代码的 tp5_小程序·云开发优劣简述