10

基于嵌入式 Linux 的设备通常需要一种机制来更新应用程序和系统文件。例如,带有 USB 端口的(非联网)实验室仪器可以从 U 盘获取软件更新。

运行脚本将文件复制到设备内部闪存上的位置将是一件简单的事情。但是,存在设备在更新过程中断电并最终变成砖块的危险。

应用程序文件的情况稍微容易一些,因为有空间复制应用程序目录、更新一个副本以及快速交换新旧目录,从而最大限度地减少故障窗口。

对于内核和系统文件来说,事情变得更加复杂,因为它们分布在整个文件系统中。

我们在文件系统中使用硬链接和软链接来识别关键文件。我们对文件和档案使用哈希来验证文件完整性。如果从更新的文件系统启动失败,我们已经考虑在内核中使用紧急 ramfs 来提供回退。

你对这个要求有什么方法?

4

5 回答 5

2

如果一定要保证可靠性,可以有两个闪存分区(甚至芯片),一个是当前工作配置,一个是新配置。然后使用硬件看门狗将重置单元并将活动引导闪存分区切换到“最后一次正确”配置。

于 2008-11-13T16:10:13.050 回答
2

至少有两个分区。我建议4

  • 开机

  • 备用引导

  • 程序数据备份

  • 程序易失性数据

如果引导失败,请使用 grub 后备引导来替代引导。

因此,如果更新失败,替代方案将起作用。

永远不要更新引导加载程序。

如果数据分区已烘烤,请重新格式化并复制备份数据分区。

现在你不能失败,除非闪存盘死了。如果您使用的是 COTS 硬件,并且主磁盘是紧凑型闪存,那么您可以在一个小 USB 密钥上进行物理隔离备份。

于 2009-12-01T05:56:47.293 回答
1

我会采用与应用程序文件相同的方法:制作关键文件并完成自己的分区,链接到它们,然后复制分区。在所有初始化中,您应该首先检查链接是否全部显示到同一个分区,如果没有,请将它们重置(到具有某个文件最新日期的文件的分区)。如果要更新,只需将所有内容复制到新分区上,如果一切正常(crcs ok),则循环遍历文件并为每个文件系统设置从一个文件系统到另一个文件系统的链接。

这样,您的关键文件应该始终处于正常状态。

场景:

  1. 将文件复制到新分区时更新失败

    没问题,因为链接仍然显示为旧的工作链接。

  2. 链接时更新失败

    没问题,因为所有新文件都是有效的并且已经复制(否则重新链接步骤不会开始),设置检查更正此

于 2008-11-13T16:11:30.767 回答
0

恕我直言,任何非原子更新都可能破坏系统或使一致性检查变得非常困难。我同意必须避免更新引导加载程序,因为它不是断电安全的。通常,制造商希望将固件 xxx 更新到 yyy 版本,而无需担心内核和/或单个文件是否已更新。更新单个文件可能成为服务的噩梦,因为很难理解客户硬件上运行的内容。也许您正在将双副本方法(应用程序是多余的)与单副本方法混合使用。我认为这并没有太大帮助,因为系统的完整性是由链中的弱组件完成的。如果根文件系统的更新失败,那么复制应用程序并不重要。

如果您需要,双副本方法可以保证更新而不会停止服务。但它需要大量资源,因为必须复制所有组件。就个人而言,我使用回退方法,如果主应用程序失败或上次更新不成功,则在 RAM 中启动一个小的 rootfs。如果出现任何问题,此后备系统由引导加载程序自动启动,通过 USB 笔更新系统(如果需要本地更新)。

我从来没有找到一个关于这些问题的 OSS 项目,最近我根据我以前的经验开始了一个新项目。我有几个产品在运行它,我的客户对此很满意。

也许你可以看看它。您可以在以下位置找到“swupdate”(项目名称)的来源github.com/sbabic/swupdate

斯特凡诺

于 2014-01-02T12:45:53.353 回答
0

我认为您在这里试图实现的是更新过程的原子性。原子性对于嵌入式设备至关重要,其中一个突出的原因是功率损耗;但可能还有其他硬件/网络问题。我在更新上下文中使用的原子性定义是:

  • 更新总是要么完全完成,要么根本不完成
  • 除了更新程序之外,没有任何软件组件会看到安装了一半的更新

对于嵌入式 Linux,您可能需要更新多个软件组件以及可供选择的不同设计;这里有一篇论文:https ://mender.io/user/pages/04.resources/_white-papers/Software%20Updates.pdf

于 2016-08-04T22:45:44.197 回答