刘庆敏 博客linux,Linux内核源码分析--zImage出生实录(Linux-3.0 ARMv7)

内核根目录下的vmlinux映像文件是内核Makefile的默认目标。这个vmlinux映像的生成可以通过阅读内核Makefile文件得知,简单的说:Makefile解析内核配置文件.config,递归到各目录下编译出.o文件,最后将其链接成vmlinux。而这个链接成的vmlinux文件是一个包含内核代码的静态可执行ELF文件,你可以通过file命令来验证这一点。她不能通过bootloader引导并启动,如果想要使其可引导,必须使用编译工具链中的objcopy命令把这个ELF格式的vmlinux转化为二进制格式才行。

而平常使用的zImage文件就是这个vmlinux文件经过多次的转换得到的。现在就来仔细研究一下她的生成过程。

(1)arch/$(ARCH)/Makefile

首先嵌入式中经常使用的编译目标zImage并不在顶层Makefile文件中,而在被顶层Makefile包含的arch/$(ARCH)/Makefile文件中,对于ARM处理器来说就是arch/arm/Makefile文件。其中的部分规则如下:

……

# Default target when executing plain make

ifeq ($(CONFIG_XIP_KERNEL),y)

KBUILD_IMAGE := xipImage

else

KBUILD_IMAGE := zImage

endif

all:$(KBUILD_IMAGE)

boot := arch/arm/boot

archprepare:

$(Q)$(MAKE) $(build)=arch/arm/tools include/generated/mach-types.h

# Convert bzImage to zImage

bzImage: zImage

zImage Image xipImage bootpImage uImage:vmlinux

$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@

……

从这里可以看出,zImage的依赖是顶层vmlinux文件,下面的命令展开得到:

make -f scripts/Makefile.build obj= arch/arm/boot MACHINE=arch/arm/mach-* arch/arm/boot/ zImage

可以看出zImage其实是make解析arch/arm/boot目录下的Makefile文件生成的,而参数传递了目标芯片信息和目标“arch/arm/boot/zImage”。所以zImage其实是在arch/arm/boot目录下完成编译的,这就是为什么可引导zImage映像会在arch/arm/boot目录下。

(2)arch/$(ARCH)/boot/Makefile

现在来分析一下arch/arm/boot/Makefile中的部分规则,看看目标zImage的生成:

$(obj)/Image: vmlinux FORCE

$(call if_changed,objcopy)

@echo ' Kernel: $@ is ready'

$(obj)/compressed/vmlinux: $(obj)/Image FORCE

$(Q)$(MAKE) $(build)=$(obj)/compressed $@

$(obj)/zImage:$(obj)/compressed/vmlinux FORCE

$(call if_changed,objcopy)

@echo ' Kernel: $@ is ready'

先看最后一行,从中可以得知arch/arm/boot/zImage的依赖目标是arch/arm/boot/ compressed/vmlinux,且目标zImage是其二进制化的产物。

而arch/arm/boot/compressed/vmlinux是如何得到的呢?再看上一规则,arch/arm/boot/compressed/vmlinux的依赖目标是arch/arm/boot/Image。这个依赖目标的生成由最上面的规则决定,显然arch/arm/boot/Image是由顶层vmlinux二进制化得到的。而中间这行规则的含义是arch/arm/boot/compressed/vmlinux由make解析arch/arm/boot/compressed/目录下的Makefile文件生成的,这条命令展开得到:

make -f scripts/Makefile.build obj= arch/arm/boot/compressed arch/arm/boot/compressed/vmlinux

(3)arch/$(ARCH)/boot/compressed/Makefile

最后就来分析一下arch/arm/boot/compressed/Makefile中的部分规则,看看arch/arm/boot/compressed/vmlinux 的生成:

......

suffix_$(CONFIG_KERNEL_GZIP) = gzip

suffix_$(CONFIG_KERNEL_LZO)  = lzo

suffix_$(CONFIG_KERNEL_LZMA) = lzma

......

$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \

$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE

$(call if_changed,ld)

@$(check_for_bad_syms)

$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE

$(call if_changed,$(suffix_y))

$(obj)/piggy.$(suffix_y).o: $(obj)/piggy.$(suffix_y) FORCE

......

上面的第一条规则就说明了:其实arch/arm/boot/compressed/vmlinux是由几个部分根据arch/arm/boot/compressed/vmlinux.lds 脚本链接而成的:

$(obj)/$(HEAD):arch/arm/boot/compressed/head.o,在链接时处于vmlinux的最前面,其主要作用就是做一些必要的初始化工作,如初始化CPU、中断描述符表IDT 和内存页目录表GDT等等,最后跳到misc.c中的decompress_kernel函数进行内核的自解压工作。

$(addprefix $(obj)/, $(OBJS)):arch/arm/boot/compressed/ misc.o,位于head.o之后,是内核自解压的实现代码。

以下假定是gzip模式压缩:

$(obj)/piggy.$(suffix_y).o:arch/arm/boot/compressed/ piggy.gzip.o,其实是arch/arm/boot/Image经过gzip压缩后(piggy.gzip),再借助piggy.gzip.S一起编译出的ELF可链接文件。其中的原理可以看看piggy.gzip.S源码:

.section .piggydata,#alloc

.globlinput_data

input_data:

.incbin"arch/arm/boot/compressed/piggy.gzip"

.globlinput_data_end

input_data_end:

这里我还是要额外的提一下gzip压缩,也就是$(call if_changed,$(suffix_y))这个过程。这个命令认真解析起来比较麻烦,这里如果有兴趣的读者可以自行分析。这里介绍两篇经典的分析文档:《kbuild实现分析》、《Kbuild系统原理分析》,读者可自行上网下载学习。这里我直接给出了结果,这条命令执行了在Makefile.lib(scripts)中定义的:

cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \

(rm -f $@ ; false)

也就是说,piggy.gzip是将arch/arm/boot/Image文件cat到标准输出,并通过管道传入gzip命令(gzip -n -f -9)的标准输入,最后将gzip的输出重定向到目标piggy.gzip

而这个piggy.gzip文件有一个重要的特性:最后的四个字节,是文件压缩前的大小数据,存放格式是小端模式。这个数据在zImage自解压时会被用于程序得到内核解压后所需要的空间!!!

感兴趣的朋友可以自己随便用“gzip -n -f -9”压缩一个文件试试,验证一下,我已亲自验证过了。

这样跟踪下来,zImage的产生过程已经看完了,但是读者可能会被这有点复杂的关系绕晕了,所以现在可以结合一下的流程图简单地总结一下:

首先顶层vmlinux是ELF格式的可执行文件,必须将其二进制化生成Image后才可以被bootloader引导。为了实现压缩的内核映像,arch/arm/boot/compressed/Makefile又将这个非压缩映像Image做gzip压缩,生成了piggy.gzip。但要实现在启动时自解压,必须将这个piggy.gzip转化为.o文件,并同初始化程序head.o和自解压程序misc.o一同链接,生成arch/arm/boot/compressed/vmlinux。最后arch/arm/boot/Makefile将这个ELF格式的arch/arm/boot/compressed/vmlinux二进制化得到可被bootloader引导的映像文件zImage。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/557063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HSSFworkbook,XSSFworkbook,SXSSFworkbook区别总结

HSSFworkbook,XSSFworkbook,SXSSFworkbook区别总结 用JavaPOI导出Excel时,我们需要考虑到Excel版本及数据量的问题。针对不同的Excel版本,要采用不同的工具类,如果使用错了,会出现错误信息。JavaPOI导出Excel有三种形式&#xff…

android项目小说阅读开发背景颜色,Android 小说阅读护眼模式

Android 小说阅读护眼模式实现方案:采用全局dialog 覆盖APP 悬浮在 其他APP之上,给dialog设置护眼色值自定义护眼模式dialogpublic class EyeProtectionDialog extends Dialog {ImageView iv;public EyeProtectionDialog(NonNull Context context) {sup…

XSSFWorkbook与HSSFWorkbook的区别

HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx

Android的APP多版本,Android多版本共存-基于gradle实现debug版和release版app共存

在开发中,测试环境与正式环境是分开的,常常需要修改配置打不同环境下的apk,而且如何在android平台下让debug和release的app共存?本着提高效率避免重复工作的目的与大家分享一个方案。本文是基于强大的AndroidStudio的构建工具gradle来实现的。…

java用XSSFWorkbook实现读写Excel

写在最前面&#xff1a;     使用的是JAVA POI实现的导出Excel&#xff1b;     POI 提供了对2003版本的Excel的支持 ---- HSSFWorkbook     POI 提供了对2007版本以及更高版本的支持 ---- XSSFWorkbook 引入相关依赖&#xff1a; <dependency><groupId&g…

android 代码植入,Android Studio之Debug(一):运行期代码植入

我们开发中经常使用IDE的Debug功能&#xff0c;使用最频繁的就是断点查看变量内容&#xff0c;这篇文章主要是介绍在Debug时很常用的一些功能&#xff0c;如Debug变量更新、动态代码植入等。背景看下面一段代码DataToStringAllArgsConstructorpublic class User {private Strin…

Java中导入、导出Excel——HSSFWorkbook 使用

一、介绍 当前B/S模式已成为应用开发的主流&#xff0c;而在企业办公系统中&#xff0c;常常有客户这样子要求&#xff1a;你要把我们的报表直接用Excel打开(电信系统、银行系统)。或者是&#xff1a;我们已经习惯用Excel打印。这样在我们实际的开发中&#xff0c;很多时候需要…

android系统电视缺点,高清智能电视安卓系统优势与不足解析

今年&#xff0c;高清智能电视开始成为平板电视市场的一大焦点&#xff0c;其凭借丰富的应用软件打下了大片的“江山”&#xff0c;作为高清智能电视&#xff0c;其高清晰度画面是必然的追求&#xff0c;而应用的丰富度是其最大的买点&#xff0c;其中最为关键的当属智能操作系…

SXSSFWorkbook使用——使用excel模板

public class Hello {public static void main(String[] args) {// 1.导入excel模板String targetPath rs.getSession().getServletContext().getRealPath("/excelModel/" fileName ".xlsx");// 2.创建一个workbook&#xff0c;对应一个Excel文件File f…

android 跳转动画黑屏,Android8.0 适配解决页面跳转过程出现短暂黑屏的问题

小菜在适配 Android8.0 过程中&#xff0c;遇到很多问题&#xff0c;有很多很常见的问题&#xff0c;今天来整理一下页面跳转时黑屏的问题。问题猜测猜测一&#xff1a;显示 Activity 页面之前会优先开启一个 Starting Window(Preview Window)&#xff0c;等待 Activity 加载完…

基于流的EXCEL文件导出,SXSSFWorkbook源码解析

当我们在实现excel导出时&#xff0c;在数据量过大的情况下&#xff0c;总是容易发生内存溢出的情况。我们可以使用POI提供的 SXSSFWorkbook 类来避免内存溢出。 注&#xff1a;基于POI4.10版本源码 以下是官方文档对SXSSF包的说明&#xff1a; SXSSF (package: org.apache.p…

android设置错误页面,Android ViewPager设置当前项目/页面时抛出IndexOutOfBounds异常

我有一个ViewPager有三个项目.我试图设置ViewPager查看最右边的页面(这将是第二个元素).这是返回IndexOutOfBounds异常,虽然我知道索引应该在边界.这是确切的堆栈&#xff1a;02-22 12:22:50.256: E/AndroidRuntime(384): FATAL EXCEPTION: main02-22 12:22:50.256: E/AndroidR…

【POI】读取Excel表中的数据

确认需要读取的表格的内容: 导入依赖&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.1</version></dependency>package com.example;import org.apache.poi.s…

w15php系列之基础类型

一、计算100之内的偶数之和 实现思路 所有的偶数除2都为0 代码实现 <?php # 记录100以内的偶数和 $number1; $num0; while($number<100){if($number%20){ $num$number;}$number1; } echo $num; ?>输出的结果 二、计算100之内的奇数之和 实现思路 所有的奇数除…

android 从本地服务器下载文件,Retrofit2-如何从服务器下载文件

在这篇博客中&#xff0c;将会讲述使用Retrofit十分需要的一个功能&#xff1a;怎么去下载文件&#xff0c;下面会展示一些下载文件需要写的代码片段&#xff0c;从小的 png 图片到大的 zip文件。

Java操作Excel中HSSFCell.CELL_TYPE_STRING、BOOLEAN、NUMERIC无定义解决方法

错误原因&#xff1a;jar包版本更新&#xff0c;官方改动&#xff1b; 解决方法&#xff1a; 导入CellType包import org.apache.poi.ss.usermodel.CellType 使用CellType.STRING代替HSSFCell.CELL_TYPE_STRING 其他同理。 新版&#xff1a; if(cellnull||cell.equals(null)…

android x86_64 服务器运行,魔趣 android10 编译x86-64 运行模拟器

cd 代码目录. build/envsetup.shlunch出现1. aosp_arm-eng2. aosp_arm64-eng3. aosp_car_arm-userdebug4. aosp_car_arm64-userdebug5. aosp_car_x86-userdebug6. aosp_car_x86_64-userdebug7. aosp_x86-eng8. aosp_x86_64-eng9. car_x86_64-userdebug10. m_e_arm-userdebug11.…

RoundingMode 几个参数详解

第一版 java.math().RoundingMode里面有几个参数搞得我有点晕&#xff0c;现以个人理解对其一一进行总结&#xff1a; RoundingMode.CEILING&#xff1a;取右边最近的整数 RoundingMode.DOWN&#xff1a;去掉小数部分取整&#xff0c;也就是正数取左边&#xff0c;负数取右边…

android资源透明背景,@谷歌android帝 这是你想要的,全局透明背景教程,两种方法...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼首先大家提取原生态没有任何修改过的framework-res.apk&#xff0c;反编译&#xff0c;(这里特别交代一下&#xff0c;大家要看仔细了&#xff0c;全局背景化透明化的修改是有两种修改的方法&#xff0c;大家可以根据自己喜好来修改…

关于异常nested exception is java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileItemFactor

简单看了一下发现原来是没有commons-fileupload包导致的&#xff0c;然后就在pom里加入了依赖。 <dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dep…