【Android】Android中的系统镜像由什么组成?
文章目录
- 总览
- Boot Loader 的加锁与解锁
- Boot 镜像
- 内核
- RAM disk
- ARM 中的设备树 (Device Tree)
- /System 和/Data 分区镜像
- 参考
总览
各种Android设备都只能刷专门为相应型号的设备定制的镜像。
厂商会提供一套系统镜像把它作为“出厂默认”的 Android 系统刷在设备上。
一个完整的系统镜像是由以下几个文件组成的,刷机时它们会被写入各自对应的分区中。
- Boot Loader:
其中含有在启动阶段由应用处理器 (application processor)执行的代码。这些代码一般是用来寻找和加载 boot 镜像的,但同时也被用来进行固件升级和让系统启动到recovery模式下。大多数 Boot Loader 还会实现一个小小的USB栈(USB stack),通过它,用户在电脑上就可以控制启动和升级过程,通常是通过 fastboot。Boot Loader会被刷到“aboot”分区里去。 - boot镜像:
它一般是由内核和 RAM disk 组成的,作用是加载系统。假设启动正常,RAM disk 会被 Android 用作 root 文件系统,其中的/init.rc
及相关文件规定了系统余下的其他部分该如何被加载。boot 镜像会被刷到“boot”分区里去。 - recovery镜像:
这个镜像同样是由内核和(另一个)RAM disk 组成的,一般用来在正常启动失败或者通过 OTA 升级时,把系统加载到“recovery 模式”。这个镜像会被刷到“recovery”分区上。 - /system 分区镜像:
这里存放的是一个完整的 Android 系统,其中除了谷歌提供的二进制可执行文件和框架(framework) 之外,还有厂商或运营商提供的类似的东西。 - /data 分区镜像:
这里存放的是“默认出厂设置”的数据文件,它们是/system 分区中程序正常运行所必需的文件。当手机需要重置到“出厂状态”时,也只需把这个分区镜像刷写到/data 分区,覆盖掉原来的数据即可。
Boot Loader 的加锁与解锁
Android 设备上的 Boot Loader 一般都会被加锁。也就是说,如果数字签名验证没有通过,手机/平板电脑会拒绝刷机或用更新的镜像启动。厂商会在 ROM 中提供他们的公钥,该密钥被用来建立一条贯穿启动过程始终的信任链。这样,所有的启动组件(从rpm到 sbl再到Android Boot Loader)就都可以被验证 (是否来自厂商或有无遭到修改)了。对这些组件的逆向分析表明,其中都有一个X.509v3 的证书,以及验证密钥时所必需的 OpenSSL 相关代码。
被解锁之后(如果可能的话), Boot Loader 就能完全控制/data 分区中的信息。所以解锁 BootLoader 会从根本上危及手机的安全性,因为攻击者拿到手机之后,就能给手机刷一个能绕过用户的开机密码或者锁屏图案的恶意更新包,或者把/data 分区中的数据复制出来,把里面的所有个人信息全部偷走。
如果 BootLoader 不能解锁,那么至少从理论上说,只要不被 root,手机就是安全的。不过在实践中,Android 也并不是不存在能够 root 它的漏洞。事实上,任何一个 3.13 及以后版本的Linux内核漏洞利用代码都有可能被用来 root Android 系统。著名的“TowelRoot”(这个漏洞利用代码是由 GeoHot 公开的)会影响到目前市场上销售的所有 Android 设备,而这还只是好几个般被称为“一键 root”(相当于 iOS 中的越狱程序)的漏洞利用程序中的一个。
Boot 镜像
Android 的 Boot 镜像中存储的是操作系统的核心组件,包括内核和 RAM disk。此外,Boot镜像(它是由Android 源码树中的 mkbootimg 创建的)的组成部分还有一个很小的头部、内核命令行、一个 Hash以及一个可选的(在实践中并不使用的)二级启动加载器。
所有这些组件都是闪存页边界(通常为2KB)对齐的。Boot 镜像可以用它的文件签名“ANDROID!”予以识别,这和上文中我们可以用Boot Loader 的文件签名“BOOTLDR!”识别 Boot Loader 的原理是一样的。
内核
与大多数操作系统的内核不同,Linux 的内核大多是经过压缩的。内核镜像文件格式(也被称为 zImage 格式)规定,其中必须含有用来把内核镜像中其他经过压缩的部分解压到内存中去的自解压代码。由于不同压缩算法各有所长,所以可选的压缩算法也有好几个,具体使用哪种算法是在 build 内核的过程时 (make config)决定的,如图:
内核总是会先运行自解压代码,这也就意味着,我们得先搜索一下文件,找到压缩算法的签名。传统上,大多数ARM 内核使用的都是 zmage,尽管严格意义上说并不一定要这样做。
内核是 Android 系统中与体系结构最为紧密相关的部分。尽管其他的一些组件也需要关心处理器的类型 (系统中使用的到底是 ARM、Intel 还是 MIPS 处理器),但是内核还要关心主板类型和芯片组的型号。因为事实上,移动设备的处理器是个单晶片系统(SoC,System-on-Chip,它由一组芯片构成),其中还含有其他芯片,内核也必须为这些芯片提供专用的驱动。这些驱动是源码树的一部分,谷歌为不同的芯片组提供了不同的内核设备树 (device tree)。
RAM disk
Boot或recovery 镜像的另一个组件就是“initialRAM disk”,它通常也被简称为initrd。RAMdisk 提供了最初的文件系统,在操作系统启动时,它被用作根文件系统(/)。它会和内核一起被 BootLoader 预加载到 RAM (也就是内存,所以得名 RAM disk)中去,所以是可以直接访问而不需要经过任何特殊的驱动的。
这并不是一个 Linux 特性,我们知道,在其他一些 UNIX 系统中也使用它,其中最著名的当属iOS 了,尽管 iOS 中是把它和
kernel cache 并排放在ipsw 系统镜像里的。
传统上,initramfs 是用来提供内核操作时所需的相关设备的驱动程序的。在它的帮助下,Linux 发行版本才能提供一个通用的、相对紧凑的内核,并在最开始安装的过程中,把所需的驱动打包放进一个单独的文件中。
为了解开“先有鸡还是先有蛋”,即加载驱动先要能访问存储器,而要能访问存储器又先要有存储器的驱动这个死结,一些关键的必备驱动会被打包放在 intramfs 中。这样,内核就能直接在 RAM中访问到它们了。initramfs 中还含有一个启动程序/init,内核会把它作为系统中的第一个进程(PID=1)运行起来,用于完成一些需要在用户模式 (user mode) 下执行的初始启动操作,比如加载模块。
当RAM disk 的操作完成之后,Linux 通常都会丢弃掉它,以便使用磁盘上的文件系统,用一个通常被称为“pivoting root”的进程。
但在Android 中,initramfs 却还是会被保留在内存中用来提供根文件系统(/)。由于其中的文件会被经常访问,而且 RAM disk 本身所占的内存空间也非常的小,所以这样做还是很有用的。此外,这么做也使得修改根文件系统的难度变得更大了一些,因为 Boot 镜像是有数字签名保护的。
Linux支持两种文件格式的RAM disk–initrd (ext4文件系统镜像)和initramfs (CPIO文件)。后者更为常用,不过常常也会被称为 imitrd。CPIO 文档是一种只需占用很少内存空间的简单格式。为了进一步节省空间,该文档还会经过 gzip 压缩(内核是支持 zlib 的,因为内核要用它把自己解压出来)。
根据相关规定,内核在被压缩之后会和 RAM disk 一起放在一个单独的分区中。这背后有一个非常重要的设计思想,就是把两个东西打包在一起,只要用一个数字签名,就能同时保护这两个东西。
即,只要应用一次防篡改措施,就能保护两者都不会被篡改。内核当然是系统的关键组件,但 RAM disk 也是非常重要的,其中的/init 及其对应的/init.rc 文件控制着系统的启动过程。/init 会以 root 权限启动,负责启动所有其他的系统组件,只要修改一下/init.rc 文件就能获取设备的 root 访问权限,但只要搞不定数字签名,这一切就是水中花,井中月。
ARM 中的设备树 (Device Tree)
大多数ARM内核需要靠设备树 (device tree)文件向内核提供硬件设备定义的相关信息这个文件提供了设备相互连接的层次关系,使得内核能够据此启动相应的设备。
设备树文件一般会被附加在内核镜像的尾部,但有时也会为它专门分配一个分区。
设备树是一个二进制的 blob 文件,可以通过它的文件签名 0xd0dfeed 予以识别。
“Blob” 一词通常用来指代二进制大型对象(Binary Large Object),是一种存储二进制数据的数据类型。在计算机领域中,“blob” 可以表示任意类型的二进制数据,如图像、音频、视频等。这个术语通常用于描述数据库中存储的非结构化数据。
另外,在编程和计算机科学中,“blob” 也可能指代内存中的一块连续的二进制数据块,通常用来存储临时数据或需要以原始形式处理的数据。
/System 和/Data 分区镜像
因为厂商可以提供自己专门开发的分区刷写工具,所以,用哪种镜像文件格式存储它们完全可以由厂商自己说了算。不过由于大多数厂商使用的还都是 fastboot,所以他们很可能也就沿用了谷歌在自己的镜像上使用的 simg(sparseimage)格式。能处理这种文件格式的实用程序可以在AOSP的system/core/libsparse
目录下找到。
参考
《最强Android书:架构大剖析》
相关文章:

【Android】Android中的系统镜像由什么组成?
文章目录 总览Boot Loader 的加锁与解锁Boot 镜像内核RAM diskARM 中的设备树 (Device Tree) /System 和/Data 分区镜像参考 总览 各种Android设备都只能刷专门为相应型号的设备定制的镜像。 厂商会提供一套系统镜像把它作为“出厂默认”的 Android 系统刷在设备上。 一个完…...
仿真机器人-深度学习CV和激光雷达感知(项目2)day7【ROS关键组件】
文章目录 前言Launch 文件了解 XML 文件Launch 文件作用Launch 文件常用标签实例--作业1的 Launch 文件TF Tree介绍发布坐标变换--海龟例程获取坐标变换--海龟自动跟随例程rqt_工作箱前言 💫你好,我是辰chen,本文旨在准备考研复试或就业 💫本文内容是我为复试准备的第二个…...

解锁一些SQL注入的姿势
昨天课堂上布置了要去看一些sql注入的案例,以下是我的心得: 1.新方法 打了sqli的前十关,我发现一般都是联合查询,但是有没有不是联合查询的方法呢…...

Qt 拖拽事件示例
一、引子 拖拽这个动作,在桌面应用程序中是非常实用和具有很友好的交互体验的。我们常见的譬如有,将文件拖拽到某个窗口打开,或者拖拽文件到指定位置上传;在绘图软件中,选中某个模板、并拖拽到画布上,画布上变回绘制该模板的图像… 诸如此类,数不胜数。 那么,在Qt中我…...

Linux:命名管道及其实现原理
文章目录 命名管道指令级命名管道代码级命名管道 本篇要引入的内容是命名管道 命名管道 前面的总结中已经搞定了匿名管道,但是匿名管道有一个很严重的问题,它只允许具有血缘关系的进程进行通信,那如果是两个不相关的进程进行通信࿰…...
实习记录——第五天
今天我的心情不是很美丽,昨天晚上没怎么睡好,因为我一直在想离不离开实验室?该怎么说的事情?但是又觉得这个项目还没有完全结束,冒昧提这个事情是不是不好?最终也没得出一个结论,晚上睡得也不踏…...

Kotlin 教程(环境搭建)
Kotlin IntelliJ IDEA环境搭建 IntelliJ IDEA 免费的社区版下载地址:Download IntelliJ IDEA – The Leading Java and Kotlin IDE 下载安装后,我们就可以使用该工具来创建项目,创建过程需要选择 SDK, Kotlin 与 JDK 1.6 一起使…...

04.领域驱动设计:了解聚合和聚合根,怎样设计聚合-学习总结
目录 1、概述 2、聚合 3、聚合根 4、怎么设计聚合 4.1 聚合的构建过程主要步骤 第 1 步:采用事件风暴。 第 2 步:选出聚合根。 第 3 步:找出与聚合根关联的所有紧密依赖的实体和值对象。 第 4 步:画出对象的引用和依赖模型…...

cmake-find_package链接第三方库
文章目录 基本调用形式和模块模式使用方式 之前我们是使用了绝对路径来链接OpenCV第三方库,但是现在很多库一般会自己写一些cmake文件提供给用户,用户可以直接使用其中的内置变量即可。使用的命令就是find_package。 基本调用形式和模块模式 find_packa…...

obsidian阅读pdf和文献——与zotero连用
参考: 【基于Obsidian的pdf阅读、标注,构建笔记思维导图,实现笔记标签化、碎片化,便于检索和跳转】 工作流:如何在Obsidian中阅读PDF - Eleven的文章 - 知乎 https://zhuanlan.zhihu.com/p/409627700 操作步骤 基于O…...

走方格(动态规划)
解题思路: 找边界,即行为1,列为1。 拆分问题,拆分成一次走一步,只能向右或者向下走。 解题代码: public static void main(String[] args) {int [][]arrnew int[31][31];Scanner scnew Scanner(Sys…...

基于DataKit迁移MySQL到openGauss
📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…...

API网关-Apinto压缩包方式自动化安装配置教程
文章目录 前言一、Apinto安装教程1. 复制脚本2. 增加执行权限3. 执行脚本4. Apinto命令4.1 启动Apinto4.2 停止Apinto4.3 重启Apinto4.4 查看Apinto版本信息4.5 加入Apinto集群4.6 离开Apinto集群4.7 查看Apinto节点信息 5. 卸载Apinto 二、Apserver(Apinto Dashboard V3)安装教…...

内网穿透natapp使用教程(Linux)
我的使用场景:在家访问学校服务器,由于不在一个局域网,所以需要使用内网穿透,我使用的是natapp。需要在有局域网的时候做好以下步骤。 (natapp官网:https://natapp.cn/) 1. 下载客户端 &#x…...
php函数 二
一 字符串包含 1.1 str_starts_with(string $haystack, string $needle) php8版本中新函数。 检查字符串是否以指定子串开头,区分大小写。返回布尔值。 $haystack待判断的字符串,$needle需要查询的内容。 function test1() {$str "Qwe asd zx…...

IDC机房交换机核心技术与应用指南
IDC机房交换机核心技术与应用指南 在这个快速发展的数字时代,数据中心作为信息技术的心脏,不仅承载着海量数据的处理、存储和传输,更是支撑着全球企业运营和互联网服务的关键基础设施。在众多构成数据中心的组件中,IDC机房交换…...
Compose | UI组件(五) | Button 按钮组件
文章目录 前言Button 是什么?Button的创建Button显示水平方向的UI IconButton是什么?IconButton是创建 FloatingActionButton是什么?FloatingActionButton创建 ExtendedFloatingActionButton是什么? 总结 前言 随着移动端的技术不…...
【leetcode刷刷】235. 二叉搜索树的最近公共祖先 、701.二叉搜索树中的插入操作 、450.删除二叉搜索树中的节点
235. 二叉搜索树的最近公共祖先 class Solution:def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:# 递归if not root: return if root.val p.val: return pif root.val q.val: return qleft Noneright Noneif root.val > p.…...

YoloV8改进策略:BackBone改进|DCNv4最新实践|高效涨点|多种改进教程|完整论文翻译
摘要 涨点效果:在我自己的数据集上,mAP50 由0.986涨到了0.993,mAP50-95由0.737涨到0.77,涨点明显! DCNv4是可变形卷积的第四版,速度和v3相比有了大幅度的提升,但是环境搭建有一定的难度,对新手不太友好。如果在使用过程遇到编译的问题,请严格按照我写的环境配置。 …...

高中数学常识
一、大小关系 |x| > |sinx| 理由: 很明显,在圆内,弧长x>垂线sinx 3x、2x 、 1 2 \frac{1}{2} 21x 理由: log 1 2 _\frac{1}{2} 21x、log 2 _2 2x、 log 3 _3 3x 二、(xy)? 的求法 利用二项式定理 三、平…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
规则与人性的天平——由高考迟到事件引发的思考
当那位身着校服的考生在考场关闭1分钟后狂奔而至,他涨红的脸上写满绝望。铁门内秒针划过的弧度,成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定",构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...