2025年Android新特性virtualAB总结

Android新特性virtualAB总结一 原理 一 Virtual A B 分区布局 上面这个表是 Virtual A B 分区布局 其中 这些分区对于引导非常重要 它是由引导加载程序直接加载的 所有启动关键分区都有一个 A 和一个 B 副本 大多数启动关键分区都很小 例如 vbmeta 是 64KiB boot 是 64MiB

大家好,我是讯享网,很高兴认识大家。

一、原理

(一)Virtual A/B分区布局


讯享网

上面这个表是Virtual A/B分区布局

其中

这些分区对于引导非常重要,它是由引导加载程序直接加载的。

所有启动关键分区都有一个A和一个B副本。大多数启动关键分区都很小。例如,vbmeta是64KiB, boot是64MiB, dtbo是8MiB等等。创建这些分区的A/B副本所需的空间相对较少。

 

其他这些分区是动态的,所以它们包含在super中。

(二)virtualAB新特性:快照合并

1、名字解释

先解释几个名词

(1)、解释snapshot快照

Ok,这里出现一个名词需要解释一下snapshot——快照技术

我不想把百度百科上面一堆看不懂的句子放在这。简单解释一下

快照技术本身可以看做是一种备份技术,但快照技术和传统备份技术有区别

区别在于打个比方

我有一串数据“ABCDEF”,存储的地址是从0x0到0x5

备份就是我找一块空间0x7到0x12,我把数据完全的拷贝到这块空间

从这里看备份的缺点很明显,如果数据比较大,但改动又不多或者集中在某个区域,就很占用空间

而且比如我就1000位数据我常改其中50位的数据,你就都备份,那有浪费了950位数据的额空间

而快照技术并不备份所有数据,我只记录上次对这部分数据进行写操作的时间点和改动的数据(不是全部数据),这样我要记录的数据比起把数据全部备份就少的多了。

快照技术分为两种:写时复制和 I/O 重定向

 

写时复制就是比如我要把“ABCDEF”这串数据(存储的地址是从0x0到0x5)改为“ABCMEF”,只把其中的D改为M

如果是写时复制,就是我先把元数据读出来(从0x3读出D),然后把D改成M,然后改动的数据写在另一个位置(快照),然后再把改动的数据写到元数据处(0x3)

所以可以看到一次写时复制进行快照需要一次读操作,两次写操作,如果数据改动非常频繁,我改一次数据却需要花3次I/O时间

所以如果写操作过于分散且频繁,那么 COW造成的开销则是不可忽略的,有时甚至是无法接受的。因此在应用时,则需要综合评估应用系统的使用场景,以判断这种方式的快照是否适用。

然后读数据的时候,因为元数据的位置已经改动了,所以我无需去读快照空间的数据来获取,直接读元数据的位置就好

这是写时复制

 

如果是I/O重定向,还以比如我要把“ABCDEF”这串数据(存储的地址是从0x0到0x5)改为“ABCMEF”,只把其中的D改为M举例

首先从先把元数据读出来(从0x3读出D),然后把D改成M,然后改动的数据写在另一个位置(快照),

注意到这就不一样了,不改动元数据位置的数据,就是说0x3处还是D

所以这样一次快照就是一次读操作,一次写操作

然后下次写操作还是一样。

如果是读操作,会先用上次读快照的操作时间和最新写快照的时间进行对比。

如果在上次读快照后有最新的写快照,那就说明数据改动了。就会把自上次读快照至最新写快照这段时间内的所有写快照合并,然后一起去改动元数据。然后新建读快照

如果在上次读快照后没有最新的写快照,那就说明数据没有改动,直接读元数据处的数据就好

所以从这里可以看出I/O重定向可以将多次写操作合成一次去修改元数据。

比如我改四次数据,写时复制每次一次读操作,两次写操作,总共4次读操作,8次写操作。

如果是I/O重定向,写快照每次一次读操作,一次写操作总共4次读操作,4次写操作

然后我改完四次数据后,再读数据,把4个快照合成最新一次的改动的数据,去修改元数据,这样就当写操作频繁时,可以将修改元数据的写操作多次合成一次来进行

Snapshot这个名字的解释就解释到这里

(2)、解释dm-verify

dm-verity是一个虚拟块设备,专门用于文件系统的校验。

fs在挂载的时候直接指定dm-verity设备,也就是fs直接交互的设备是dm-verity,dm-verity调用真正的块驱动去读取对应的块,并计算hash值和hash-tree中对应的hash值进行比较,如果相等,则说明块没有被篡改,返回块数据给fs,如果不相等,则说明块被篡改,根据mode是返回EIO,或者直接重启。

所以dm-verity是为了防止文件系统被更改进行校验的虚拟块设备。而且因为dm-verity并不需要在挂载前对所有的块进行校验,而是在使用的过程中用到哪个块就校验哪个块的hash值,所以dm-verity比起在挂载前对所有的快进行校验的方式要快很多

(3)、解释dm-linear

Dm-linear是linux的一种映射机制。(linear是线性的意思)这个我不想摊开讲了,用kernel官网上的一句话来解释一下就好了

Device-Mapper’s “linear” target maps a linear range of the Device-Mapper device onto a linear range of another device. This is the basic building block of logical volume managers.

线性存储子系统的目的就是将设备的一块线性地址范围映射到另一个设备的线性地址范围。

(4)COW

COW如果你直接翻译就是奶牛的意思,这肯定不对,COW一定是缩写

COW是copy-on-write的缩写,中文就是写时复制

好了,之前说快照的时候有介绍写时复制,这里不再重复

所以我们就明白了这里就是要说如何对system分区进行快照,采用的快照技术是写时复制

2、virtualAB快照合并新特性

VirtualAB实现了write-to-snapshot模型,这意味着在更新成功引导之后,会发生一个合并阶段。

一开始,从来没有对system分区进行过更改操作,

设备看起来是这样的,假设设备在A槽上(以system分区举例):

 

之前有解释过名词dm-verity和dm-linear,

这里就是三步:挂载system,访问system时进行dm-verity校验,然后对要访问的地址进行映射

继续

当需要更改system分区,system就需要进行快照操作,具体操作如下:

1. 先创建由调整大小的system_a分区(称为system_b_base)组成的base设备

  1. 创建COW设备(可能由超级分区中的空闲块组成,也可能是/data上分配的块上的循环设备,或者两者都有)
  2. Base设备和COW设备都有了,base和COW设备统一作为一个快照设备。

最开始system原始数据在A槽,所以快照设备我们需要在B槽创建

 

Ok,现在来看这张图就明白多了

 

最开始没有对system进行写操作,是这样的,就是挂载上了以后,如果只是进行读操作就dm-verity校验,然后对要操作的线性地址进行映射就好了

如果要对system进行写操作,就要创建

 

由调整大小的system_a分区(称为system_b_base)组成的基本设备

 

COW设备(可能由超级分区中的空闲块组成,也可能是/data上分配的块上的循环设备,或者两者都有)COW设备(可能由超级分区中的空闲块组成,也可能是/data上分配的块上的循环设备,或者两者都有)

 

以及在base和COW上的一个快照设备

 

所以在system分区更改后,设备重启时,就必须使用快照来挂载了

当设备在应用更新后重新引导时,发现有快照设备,系统就从快照上进行挂载,直到成功引导。这次/系统是从快照上挂载的。

有快照设备,说明上次启动system分区有被更改过,那从快照设备挂载成功后,就需要把base设备和快照设备的内容合并。这样就可以删除快照设备了

这就是接下来要做的一步:merge

如果设备没有启动成功标志,就按照

不使用快照设备进行挂载,这样就可以保证一旦上次启动对system分区进行的操作造成启动不成功,就可以挂载可以启动成功的system来让系统启动

如果设备启动成功标志,那就说明挂载快照设备启动成功了,说明上次对system分区的修改没有问题,那就可以把快照COW设备和base设备进行merge,作为新的base设备。这个时候快照设备就可以删除了

 

这样下次启动的时候发现没有快照目标,

就还是最简单的三步:挂载、使用的时候校验、映射

不过要注意的是,可以看到slot发生了变化,由a变成b了

3、virtualAB和AB区别

通过上面对virtualAB原理的分析,我们可以知道virtualAB和AB分区

 

对于这些系统启动关键分区,virtualAB和AB是一样的,以为这些分区除非重烧否则不会改

但对于

 

这些在super里面的动态分区就不一样了

对于AB分区,就是传统的备份

 

也就是system_b就是system_a的副本

(但实际上比如在MTK平台,可能为了节省空间,b槽 里面压根就没有东西)

而对于virtualAB,用的就是写时复制快照技术

 

所以这些动态分区无需AB,我有修改就创建快照,下次启动如果成功,就说明对于分区的修改没有问题,就将快照和base合并,作为最新的base

所以virtualAB的优点显而易见:

  1. virtualAB备份的不是副本,而是快照。所以节省空间
  2. AB分区B备份的其实是最原始的A slot数据,如果A slot数据已经更改,B没有及时、甚至就没有更新。而virtualAB始终保存的是最新的可以成功启动的数据。

二、virtualAB快照-合并 详细步骤

我们说更新详细过程,其实也就是生成快照设备,下次启动合并base和快照设备的过程

比如我对system分区的数据进行改动

(一)更新后快照操作

 

就是对这个图进行详细解释

  1. 判断有没有正在进行的merge操作:首先如果我是在启动刚成功的时候就对system分区进行写操作,系统启动成功后,会对base设备和COW快照设备进行merge。很有可能此时还在merge中。所以如果前一个合并正在进行中,那么在gsid上注册一个通知并等待,直到前一个合并完成。
  2. 记录START开始标志位
  3. 删除旧快照数据:然后如果前一个合并完成或者没有在进行合并操作的话,就要删除快照数据。这很合理,因为快照永远是最新的,不会保留上上次的。有可能在合并完成后会自动进行删除快照操作,如果没有这样设计的话,那这里就要删除快照数据。具体如下:
  1. 把元数据(修改前的)拷贝到内存M中;
  2. 删除所有后缀带t的分区(相当于删除base设备);
  3. 删除COW设备(快照设备);

4、新建base设备

判断系统是否支持virtualAB新特性

(1)如果不支持,如果设备在A槽启动,就把对应的b槽分区分区名加上后缀_t

例如system_b改为system_b_t。来表示是一个base设备

注意,即使系统不支持virtualAB这个新特性,这一步也必须做

(2)如果支持virtualAB新特性,就新建一个分区/组,名字加上后缀_t

5、新建COW设备准备工作

(1)计算COW设备所需大小,我理解其实就是你改动了多少数据的大小和快照信息的大小。

(2)如果所需大小不大(没超过super剩余空间),就在内存M中组cow中新建 P_cow(例如system cow)逻辑分区。然后创建一个文件覆盖COW设备所需大小这么大的空间

如果所需大小比较大(super剩余空间不够使),那就创建一个空文件来覆盖所需的空间大小(需要多少就看你要占用多大的userdata分区的空间,总之不够的空间就占用userdata)

6、拷贝元数据到上面3的base设备处,也就是后缀带_t的分区

7、在/metadata或者/data写入COW设备的信息,注意COW信息还要包括base设备的分区名和槽位(A或者B)

8、记录SUPER_METADATA_AND_COW_DEVICE_READY标志位,表示准备工作都已经做好了

9、读出保存在/metadata或/data保存的COW设备信息并创建COW设备,就是把相关快照数据保存在/data中(如果super空间足够大,可能会存在super中)

10、基于base设备和COW设备创建快照设备

11、记录UPDATE_APPLIED_PENDING_REBOOT标志位,表示本次快照操作完成。

上述就是对动态分区中的相关分区修改更新操作,建立快照的整个过程

(二)快照后第一次启动

然后设备下一次启动(快照后第一次启动)

 

1、从带_t后缀的分区中读出元数据(base设备数据)

2、从/metadata或/data中得到COW设备镜像

3、上面两步base数据和COW数据都有了,所以创建base设备和COW设备,再创建结合两者的快照设备

4、挂载快照设备

5、等待启动成功

6、进行merge操作,这样新的合并数据就作为新的base数据(因为上一步启动成功,就说明上次对动态分区的更改是没有问题的)

7、等待merge结束

8、删除COW数据

(三)合并快照设备后第一次启动

然后设备下一次启动(合并快照设备后第一次启动)

 

启动发现/metadata或/data中没有COW设备镜像,就说明上次启动没有修改动态分区的数据,就正常三步:挂载,使用那一块数据就做校验,对要访问的数据进行映射。

三、virtualAB要注意的问题

我对英文文档中提到的点归纳总结一下:

  1. virtualAB采用的是快照技术中的写时复制COW技术,所以自然继承了写时复制的缺点,如果写操作过于分散且频繁,那么 COW造成的开销则是不可忽略的,有时甚至是无法接受的。因此在应用时,则需要综合评估应用系统的使用场景,以判断这种方式的快照是否适用。
  2. 在系统正在进行merge操作时,如果此时重置系统,adbfastboot、电源键进行重启关机,扣电池(断电)是非常有风险的,因为此时base设备和COW设备正在合并,如果丢失COW数据还好,如果连base数据都丢失了,系统就启动不了了。
  3. 如果super剩余空间不足,会占用userdata的空间来存储COW数据。

问题就来了

  1. 如果userdata应用更新,或者其他方式动了存储COW数据的位置,COW数据就会丢失。
  2. 有些恶意软件会占用多余的空间,造成userdata空间也不足
  1. 目前的system_a分区就是存储system.img,system_b分区存储的是一些优化数据,镜像是system_other.img。比如在DH30 Q项目存储的就是odx文件,没有的话烧录后首次开机会达到五十几秒,如果有odx文件,首次开机时间就会大大提高

virtualAB首次启动会丢弃system_b分区的数据

这一点会是系统组做开机odx优化的一个风险

  1. 实现写保护困难
  2. 按照之前的说明,是先计算COW的大小,然后再去创建COW设备进行存储的。如果计算的COW大小比super剩余空间还要大,就会占用userdata空间。所以COW数据所占空间的大小能否计算准确,至关重要。

小讯
上一篇 2025-03-23 19:21
下一篇 2025-04-04 21:50

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/57998.html