第三章 差分升级原理:差分算法与包处理流程
差分升级,说白了就是「只传变化的部分」。
我刚开始接触OTA时,也想过:为什么不直接全量升级?简单粗暴。但当你面对几百兆的固件,用户流量有限,升级失败还得重传……嗯,这时候你就知道差分升级有多香了。
3.1 差分算法的核心思想
差分算法的本质,就是对比新旧两个二进制文件,找出差异,然后只打包这些差异。
你想想看,一个固件可能只改了10%的代码,剩下的90%完全一样。如果全量传,浪费的流量和时间都是巨大的。
核心公式:
差分包大小 ≈ 新固件中变化的部分 + 控制信息
通常差分包只有全量包的 5%~30%
我在项目中遇到过最极端的案例:某个设备只改了一个配置参数,差分包只有 2KB,而全量包是 32MB。你算算,这差了 16000 倍。
3.2 主流差分算法:bsdiff 与 imgdiff
鸿蒙系统主要用了两种差分算法,各有各的适用场景。
3.2.1 bsdiff 算法
bsdiff 是二进制级别的差分算法。它不关心文件格式,只看字节流。
它的工作原理是这样的:
- 扫描旧文件,构建一个后缀数组(Suffix Array)
- 匹配新文件,在旧文件中找最长匹配子串
- 编码差异,记录匹配位置、长度和差异字节
我曾经踩过一个坑:bsdiff 对内存的消耗很大。处理 100MB 的固件,内存占用可能飙到 1GB 以上。所以嵌入式设备上,你得掂量掂量自己的内存够不够。
注意:bsdiff 适合处理二进制固件、库文件、可执行文件。但不适合处理已经压缩过的文件(比如 .zip、.jpg),因为压缩后的数据变化非常敏感,差分效率会大幅下降。
3.2.2 imgdiff 算法
imgdiff 是专门为 Android/HarmonyOS 的镜像文件设计的。它知道镜像的内部结构。
说白了,imgdiff 会先解析镜像中的文件系统,然后对每个文件单独做差分。这样更精准,效率也更高。
| 特性 | bsdiff | imgdiff |
|---|---|---|
| 适用范围 | 任意二进制文件 | 镜像文件(system.img, vendor.img) |
| 内存消耗 | 高(约 10x 文件大小) | 中等(按文件粒度处理) |
| 差分效率 | 通用但略低 | 针对镜像优化,效率高 |
| 适用场景 | bootloader、内核、驱动 | 系统分区、应用分区 |
3.3 差分包生成流程
差分包生成,是在服务器端完成的。流程大致如下:
- 获取旧固件:从设备上报的信息中,拿到当前版本
- 准备新固件:编译好的目标版本
- 执行差分算法:bsdiff 或 imgdiff,生成 .patch 文件
- 打包成差分包:加上元数据(版本号、校验值、签名等)
- 签名:防止篡改,保证安全
我建议你在生成差分包时,一定要做一次「自验证」。也就是用差分包还原出新固件,然后跟原始新固件做哈希比对。我曾经因为编译环境不一致,导致差分包还原后多了几个字节,设备直接变砖……从那以后,自验证就成了我的铁律。
小技巧:差分包生成时,可以设置一个「最小匹配长度」。比如 bsdiff 默认是 8 字节,你可以根据固件特点调整到 16 或 32 字节。匹配越长,差分包越小,但计算时间也越长。需要权衡。
3.4 差分包还原流程
还原流程是在设备端执行的。设备收到差分包后,需要把它和旧固件合并,生成新固件。
还原步骤:
- 校验差分包:检查签名和完整性
- 读取旧固件:从当前分区读取
- 执行还原算法:bsdiff 或 imgdiff 的逆向操作
- 写入新固件:写入目标分区
- 校验新固件:计算哈希,跟差分包中的元数据比对
这里有个关键点:还原过程中,设备不能断电。一旦断电,旧固件可能已经被覆盖,新固件又没写完,设备就彻底废了。
避坑指南:我曾经遇到过一个问题——设备在还原时内存不足。bsdiff 还原需要同时加载旧固件和差分包,如果设备内存只有 64MB,而固件有 100MB,那就直接 OOM 了。解决方案是「流式还原」:边读边写,不把整个文件加载到内存。
3.5 核心逻辑流程图
下面这张图,展示了差分升级的完整数据流:
3.6 实际项目中的经验总结
做了这么多年 OTA,我总结了几条经验:
- 差分算法不是万能的:如果新旧固件差异太大(比如换了内核),差分包可能比全量包还大。这时候就别硬上差分,直接全量更划算。
- 一定要做版本兼容:差分包只能从特定旧版本升级到新版本。如果设备跳版本了,你得准备多个差分包。
- 测试要覆盖边界:我建议你测试一下「空差分」(新旧固件完全一样)和「全差分」(新旧固件完全不同)这两种极端情况。
- 日志要打全:差分还原失败时,日志里要有足够的信息定位问题。我见过太多「升级失败」但不知道失败在哪里的案例了。
最后说一句:差分升级不是银弹。但它确实是目前最主流的 OTA 方案。理解了差分原理,你就掌握了 OTA 系统的核心。
公众号:蓝海资料掘金营,微信deep3321