10、VABC(Virtual A/B Compression)技术:虚拟A/B原理、Cow(写时复制)分区、压缩算法与性能优化、与经典A/B对比

各位同学,今天我们来聊一个在车载OTA里非常关键的技术——VABC。说实话,我刚接触这个名词的时候,也觉得它就是个“A/B系统的压缩版”。但真正深入项目后才发现,它背后藏着不少巧妙的设计哲学。

我个人习惯把VABC看作是“经典A/B的进化版”。它解决了经典A/B最让人头疼的问题:存储空间浪费。你想想看,经典A/B需要两套完整的系统分区,对于存储空间寸土寸金的车载设备来说,这简直是奢侈。VABC的出现,说白了就是要在保证安全性的前提下,把空间省下来。

虚拟A/B原理:不是真的“虚拟”

很多人听到“虚拟”两个字,以为是在内存里模拟一个分区。其实不是。虚拟A/B的核心思想是:在更新过程中,只保留一份完整的系统数据,另一份是“虚拟”的,通过写时复制(Cow)技术来管理差异

我在项目中遇到过这样一个场景:客户要求系统升级后,如果用户想回退,必须能100%回到旧版本。经典A/B可以轻松做到,但VABC呢?它依赖的是Cow分区来记录所有修改。只要Cow分区没被破坏,回退就是可行的。

虚拟A/B的工作流程大致是这样的:

  • 系统启动时,默认从当前活跃的slot(比如slot A)启动。
  • OTA下载完成后,系统将新数据写入到非活跃slot(比如slot B)的对应位置。
  • 但注意,这里不是全量写入。VABC只写入那些真正发生变化的数据块。
  • 对于未变化的数据块,系统通过“映射”的方式,直接引用旧slot的数据。

嗯,这里要注意:这种映射关系是动态的。系统在运行时,会维护一张映射表,告诉内核“这个逻辑块应该去物理分区的哪个位置读取”。

Cow(写时复制)分区:VABC的心脏

Cow分区,全称Copy-on-Write分区。它是VABC实现空间节省的关键。我刚开始理解Cow时,总觉得它很抽象。后来我把它想象成“一个只记录差异的笔记本”。

具体来说:

  • 当系统需要修改某个数据块时,它不会直接覆盖原数据,而是先把原数据复制一份到Cow分区,然后再写入新数据。
  • 这样,如果更新失败需要回滚,系统可以从Cow分区恢复原始数据。
  • 如果更新成功,Cow分区里的旧数据就可以被标记为“可回收”,等待垃圾回收。

核心要点:Cow分区的大小直接决定了VABC能支持多大的更新差异。如果更新涉及的数据块太多,Cow分区可能会被撑爆。我曾经在一个项目中,因为Cow分区配置过小,导致大版本升级时直接失败。后来我们根据经验,把Cow分区大小设置为系统分区的10%~15%,才稳定下来。

下面这张图展示了VABC的核心逻辑,我画了个简图帮助大家理解:

VABC 核心逻辑流程图 Slot A(当前系统) 完整系统数据 (物理分区) 启动时使用 写时复制 Cow分区 记录差异数据 (增量修改) 回滚时恢复 合并写入 Slot B 新系统 (目标) 动态映射表 逻辑块 → 物理块映射(Slot A数据 + Cow差异) 系统运行时动态维护,决定数据读取路径

压缩算法与性能优化

VABC的另一个核心是压缩算法。为什么需要压缩?因为OTA升级包通常通过网络传输,压缩可以显著减少下载时间和流量消耗。但压缩不是免费的午餐——它需要消耗CPU资源来解压。

我在项目中常用的压缩算法有几种:

  • gzip:压缩率不错,但解压速度一般。适合对带宽敏感的场景。
  • lz4:压缩率较低,但解压速度极快。适合对性能敏感的车载场景。
  • zstd:平衡了压缩率和速度,我个人比较推荐。在车载平台上,zstd的压缩率比gzip高10%~15%,解压速度比gzip快2~3倍。

我的建议:如果车载设备的CPU性能较强(比如高通SA8155以上),优先选择zstd。如果CPU资源紧张,比如一些低端MCU,lz4是更稳妥的选择。我曾经在一个项目中,因为用了gzip导致升级时CPU占用率飙到90%,差点把系统卡死。后来换成lz4,CPU占用率降到30%以下,升级体验好了很多。

性能优化方面,有几个关键点:

  • 并行解压:现代车载SoC通常有多个核心,可以利用多线程并行解压多个数据块。我习惯把解压线程数设置为CPU核心数减1,留一个核心给系统其他任务。
  • 流式处理:不要等整个升级包下载完再解压。边下载边解压,可以显著减少内存占用和等待时间。
  • 缓存策略:对于频繁访问的数据块,可以在内存中缓存解压后的结果。但要注意内存限制,车载设备的内存通常只有2~4GB。

与经典A/B对比

很多同学会问:VABC和经典A/B到底哪个好?其实没有绝对的答案,要看具体场景。我整理了一个对比表格,方便大家理解:

对比维度 经典A/B VABC
存储空间 需要两套完整分区,空间占用大 只需一套完整分区 + Cow分区,空间节省30%~50%
回滚能力 强,直接切换slot即可 依赖Cow分区完整性,回滚速度可能稍慢
升级速度 较快,全量写入 取决于差异大小和压缩算法,通常更快
实现复杂度 较低,逻辑简单 较高,需要管理映射表和Cow分区
适用场景 存储空间充足,追求简单可靠 存储空间紧张,需要频繁升级

从我的经验来看,车载设备越来越倾向于VABC。为什么?因为车载存储芯片的成本很高,能省一点是一点。而且车载OTA升级的频率越来越高,VABC的增量更新特性正好契合这个趋势。

避坑指南:我曾经在一个项目中,因为Cow分区没有做磨损均衡,导致频繁升级后Cow分区所在的Flash块提前报废。后来我们给Cow分区增加了wear-leveling支持,才解决了这个问题。如果你也在用VABC,记得关注Cow分区的寿命管理。

最后总结一下:VABC不是经典A/B的替代品,而是它的进化版。它用更聪明的空间管理策略,解决了经典A/B的痛点。但代价是增加了系统复杂度。作为工程师,我们需要根据实际项目需求,权衡利弊,做出最合适的选择。

好了,这一章的内容就到这里。希望各位同学在实际项目中,能灵活运用VABC技术,让车载OTA升级又快又稳。


公众号:蓝海资料掘金营,微信deep3321