基于嵌入式Linux的设备通常需要一种机制来更新应用程序和系统文件。例如,带有USB端口的(非联网)实验室仪器可以从USB记忆棒获得软件更新。
运行脚本将文件复制到设备内部闪存上的位置是一件简单的事情。但是,存在设备在更新过程中失去电力的危险,并最终成为一块砖。
应用程序文件的情况稍微容易一些,因为有空间复制应用程序目录,更新一个副本,并快速交换新旧目录,最大限度地减少故障窗口。
内核和系统文件的内容更加严格,因为它们遍布整个文件系统。
我们在文件系统中使用了硬链接和软链接来识别关键文件。我们在文件和存档上使用哈希来验证文件完整性。我们已经考虑在内核中使用紧急ramfs,以便在从更新的文件系统启动失败时提供回退。
您对此要求的方法是什么?
答案 0 :(得分:2)
如果必须确保可靠性,则可以使用两个闪存分区(甚至芯片),一个具有当前工作配置,另一个具有新配置。然后使用硬件看门狗,它将重置设备并将活动的引导闪存分区切换到“最后一次正确的”配置。
答案 1 :(得分:2)
至少有两个分区。我建议4
启动
备用启动
程序数据备份
程序易失性数据
如果启动失败,请使用grub fallback booting引导备用。
因此,如果更新失败,则备用工作正常。
永远不要更新启动加载程序。
如果数据分区被烘烤,请重新格式化并复制备份数据分区。
现在你不能失败,除非闪存盘死亡。 如果您正在使用COTS硬件,而主磁盘就是Compact Flash,那么您可以使用一个物理上隔离的备份,例如一个小的USB密钥。
答案 2 :(得分:1)
我会采用与应用程序文件相同的方法: 制作关键文件并完成自己的分区,链接到它们,然后复制分区。在你的所有init中,首先要检查链接是否显示所有相同的分区,如果没有,重置它们(到具有某个文件的最新日期的文件的分区)。如果你想更新只是将所有内容复制到新分区,如果一切正常(crcs ok)循环文件并为每个文件系统的链接设置为另一个文件系统。
这样,您的关键文件应始终处于理智状态。
方案:
将文件复制到新分区时更新失败
没问题,因为链接仍显示旧的工作链接。
链接时更新失败
没问题,因为所有新文件都有效且已经复制(否则重新链接步骤无法启动),设置检查正确
答案 3 :(得分:0)
恕我直言,任何非原子的更新都可能破坏系统或使检查一致性非常困难。我同意必须避免更新引导加载程序,因为它不是断电安全的。 通常,制造商需要从固件x.x.x更新到版本y.y.y,而不必在更新内核和/或单个文件时烦恼。更新单个文件可能会成为服务的噩梦,因为很难理解客户硬件上运行的是什么。也许您正在将双拷贝方法(应用程序冗余)与单拷贝方法混合使用。我认为这没有多大帮助,因为系统的完整性是由链中的弱组件完成的。如果根文件系统的更新失败,则重复应用程序并不重要。
如果您需要,双重复制方法可以保证更新而不会停止服务。但它需要大量资源,因为所有组件都必须重复。就个人而言,我使用回退方法,如果主应用程序失败或上次更新不成功,则启动RAM中的小rootfs。如果出现任何问题,这个回退系统由引导加载程序自动启动,从USB笔更新系统(如果需要本地更新)。
我从未找到关于这些问题的OSS项目,最近我根据我之前的经验开始了一个新项目。我有几个产品运行它,我的客户很满意。
也许你可以看看它。你可以找到" swupdate" ({3}}上的(项目名称)。
斯特凡诺
答案 4 :(得分:0)
我认为你在这里要实现的是更新过程的原子性。原子性对于嵌入式设备至关重要,其中一个突出的原因是功率损耗;但可能有其他人喜欢硬件/网络问题。我在更新环境中用于原子性的定义是:
对于嵌入式Linux,您可能需要更新多个软件组件以及可供选择的不同设计;这里有一篇论文:https://mender.io/user/pages/04.resources/_white-papers/Software%20Updates.pdf