当前位置:首页 > 工业控制 > 工业控制
[导读]蜂窝、NB-IoT、远程工业网关最怕整包rootfs动辄几十MB。差分升级只在服务端对“旧版本镜像/文件”和“新版本”做字节级diff,设备下小块patch,本地合成为完整新固件再写备用分区。改动比例小的时候,差分包常只有全量包10%~30%,相当于传输体积降70%左右;若大版本重排、编译器换工具链,差分包会变大,这时要回退全量。


蜂窝、NB-IoT、远程工业网关最怕整包rootfs动辄几十MB。差分升级只在服务端对“旧版本镜像/文件”和“新版本”做字节级diff,设备下小块patch,本地合成为完整新固件再写备用分区。改动比例小的时候,差分包常只有全量包10%~30%,相当于传输体积降70%左右;若大版本重排、编译器换工具链,差分包会变大,这时要回退全量。

一、服务端生成差分包

镜像级用xdelta3更省内存,bsdiff压缩率更高但合并吃RAM:

# xdelta3:旧rootfs -> 新rootfs

xdelta3 -e -9 -S none -s rootfs_v1.img rootfs_v2.img rootfs_v1_v2.xd3

# 再二级压缩,弱网更省

zstd -19 rootfs_v1_v2.xd3 -o rootfs_v1_v2.xd3.zst


# bsdiff:应用或镜像微分

bsdiff app_v1 app_v2 app_patch.bsdiff

gzip -9 app_patch.bsdiff

生成后必算摘要并写manifest,避免设备基线不一致:

sha256sum rootfs_v1.img rootfs_v2.img > base.manifest

echo '{"base":"v1","target":"v2","patch":"rootfs_v1_v2.xd3.zst","sha256":"..."}' > ota.json

# 私钥签名

openssl dgst -sha256 -sign ota_priv.pem -out ota.sig ota.json

基线必须按设备当前运行版本来;现场若写过序列号、first-boot改过镜像,patch会合成失败,所以服务端要保留最近N个旧版本基线,更老版本直接发全量。

二、设备端下载与验签

A/B分区布局简化如下:rootfs_a当前运行,rootfs_b备用,misc存active标记。下载只取差分包,按manifest验签名再验patch哈希:

curl -C - -o /data/ota/patch.xd3.zst https://ota/app/rootfs_v1_v2.xd3.zst

zstd -d /data/ota/patch.xd3.zst -o /data/ota/patch.xd3

# 公钥验签

openssl dgst -sha256 -verify ota_pub.pem -signature ota.sig ota.json

sha256sum /data/ota/patch.xd3   # 与manifest比对

-C支持断点续传;弱网用HTTP Range分片,每片写位图,失败只补缺失片。

三、本地合成新镜像

用当前运行旧分区做base,合成到临时文件,再写b分区:

# xdelta3还原

xdelta3 -d -S none -s /dev/mmcblk0p_rootfs_a \

       /data/ota/patch.xd3 \

       /data/ota/rootfs_new.img


# 或bsdiff还原应用

bspatch /dev/mmcblk0p_rootfs_a /data/ota/rootfs_new.img /data/ota/app_patch.bsdiff

合成完校目标哈希:

calc_sha=$(sha256sum /data/ota/rootfs_new.img | awk '{print $1}')

grep "$calc_sha" base.manifest || { echo "patch mismatch"; exit 1; }

bsdiff合并内存峰值高,大rootfs慎用;小应用、小镜像可用bspatch,RAM紧张改hdiff/hpatch流式合成。

四、写备用分区与原子切换

合成校验通过后写inactive槽,不改当前系统:

dd if=/data/ota/rootfs_new.img of=/dev/mmcblk0p_rootfs_b bs=1M conv=fsync

# U-Boot env切active

fw_setenv active_slot b

reboot

启动策略加看门狗和失败计数:新系统连不上、健康检查失败,U-Boot/用户态agent改回a槽。misc只存一个active标记,切换是改指针不是整包复制,断电也不会半写整系统。

五、带宽与落地账

以64MB rootfs、小版本改驱动和App为例:整包压缩后仍可能10MB+,xdelta3差分包常1~3MB,zstd再压一截,相对整包传输常可省70%以上;若只更app,bsdiff+gzip常几百KB。服务端按“版本对”预生成:v1->v2、v1->v3、v2->v3,超范围发全量。CI里固件编译完自动跑diff,工具链版本固定,避免gcc升级导致二进制全变、差分失效。

六、避坑

差分包不是万能:base哈希不一致、镜像含随机量产地数据、分区有坏块偏移,都应退化全量;

签名验签放合成前,合成后写盘前再验目标哈希,双层防篡改;

A/B存储要留“1.5个整包”空间,差分临时文件、旧base、new镜像别同时落小/tmp;

工业实时板别在业务高峰期合成,xdelta/bsdiff会占CPU,可绑低优先级核或夜间窗口;

回滚别只靠应用层,U-Boot/ATF启动计数+watchdog才是防砖底线。

按“服务端按版本对出差分+设备验签验基线和patch+A/B写备用槽+哈希全量校验+启动失败自动回滚”,嵌入式Linux既把OTA流量压下来,又保留全量兜底,适合4G/5G按流量计费的边缘网关长期运维。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭