软件修补距离十亿英里

33

有人能够解释一下NASA如何设计他们的航天器架构以确保能够修复部署代码中的错误吗?

我从未建立过任何“实时”类型的系统,这是在阅读了这篇文章后浮现出来的问题:

http://pluto.jhuapl.edu/overview/piPerspective.php?page=piPerspective_05_21_2010

“在下周唤醒宇宙飞船时,我们将首先执行的主要任务之一是上传近20个次要错误修复和其他代码增强到我们的故障保护(或“自动驾驶响应”)软件。”


好问题!将“跳出思维定式”提升到更高层次:太空,最后的边疆;-)。 - Toon Krijthe
虽然不是回答问题的直接方法,但这篇文章详细地阐述了故障排除的步骤,非常有趣:http://spaceflightnow.com/mars/mera/040126spirit.html - starblue
非常感谢大家的贡献。但是我该怎么办呢?你们所有人的答案都很好,很有帮助。我不知道该选择谁作为正确答案?更不用说这个问题并没有一个真正的“正确”答案,所有提出的观点都是有效的。 - Maxim Gershkovich
选择给你最多启示的答案。是的,你只能选择一个;生活就是这样不公平。 - Cylon Cat
哈哈,那样的话......你可能赢了!:-)该死...莱恩和格雷格·哈曼也非常有帮助...再次感谢大家,很高兴看到这么多人喜欢这个问题... - Maxim Gershkovich
5个回答

15

我曾经是公共电话交换系统软件的开发人员,该系统对可靠性、可用性、生存能力和性能有着非常严格的限制,这接近于航天系统所需的要求。虽然我没有参与过航天项目(在IBM期间我与许多前航天飞机程序员合作过),也不熟悉VXworks,但它是许多航天器使用的操作系统(包括火星探测器,它有着惊人的运行记录)。

补丁更新的核心要求之一是,系统必须从头开始设计以支持补丁更新。这包括模块结构,使得可以添加新变量并替换方法,而不会干扰当前操作。这通常意味着更改方法的旧代码和新代码都将存在,而打补丁操作只是更新类或模块的分派向量。

强烈建议将打补丁(和撤销补丁)软件集成到操作系统中。

在我从事电话系统工作时,我们通常在系统中使用补丁和模块替换功能来加载和测试我们的新功能以及错误修复,远在这些更改提交构建之前。每个开发人员都需要习惯于将打补丁和替换模块作为他们日常工作的一部分。这建立了对这些组件的信任,并确保补丁和替换代码经常进行练习。

在这些系统上的测试比你在任何其他项目上遇到的测试都要严格得多。部署系统的完整和部分模拟将随时可用。可能还会有虚拟机环境,可以运行并测试完整负载。所有高于单元测试级别的测试计划都将得到编写和形式审查,就像正式的代码检查一样(这也将是常规的)。

设计容错系统,包括软件设计,是必不可少的。虽然我不知道特定于航天器系统,但类似高可用性集群可能是标准配置,同时具备同步和异步运行的能力,并能在故障转移期间在两侧之间传输信息。这种系统结构的附加好处是,如果需要,可以将系统分割成两部分,重新加载未活动状态的一侧以获得新的软件负载,并在生产系统中进行测试,而不连接到系统网络或总线。当你确认新软件正常运行后,你可以直接切换到它。

就像打补丁一样,每个开发人员都应该知道如何进行故障转移,并应该在开发和测试过程中进行操作。此外,开发人员还应该知道会导致故障转移的每个软件更新问题,并应该知道如何编写补丁和模块替换,以避免尽可能少地进行必需的故障转移。

总的来说,这些系统从底层开始设计(包括硬件、操作系统、编译器,以及可能的编程语言),以适应这些环境。我认为Windows、Mac OSX、Linux或任何unix变种都不够稳健。其中一部分原因是实时要求,但整个可靠性和生存能力问题同样关键。

更新:另一个有趣的点是,这里有一个火星车司机的博客。这将让你了解维护操作航天器的日常生活。非常有趣!


1
这是最初的 Erlang 演示,展示了其中的一些想法。http://video.google.com/videoplay?docid=-5830318882717959520# - liori

6
我从未构建过实时系统,但在这些系统中,我怀疑它们的系统不会有内存保护机制。他们不需要它,因为他们自己编写了所有软件。没有内存保护,一个程序可以轻松地写入另一个程序的内存位置,这可以用于热修补运行中的程序(编写自修改代码是过去流行的技术,没有内存保护,同样的技术可用于修改另一个程序的代码)。
Linux 已经能够使用 Ksplice 在不重新启动的情况下进行小型内核补丁一段时间了。这对于任何停机时间可能导致灾难的情况非常必要。我自己从未使用过它,但我认为他们使用的技术基本上是这样的:
Ksplice 可以在不重新启动计算机的情况下对 Linux 内核应用补丁。Ksplice 以统一的 diff 和原始内核源代码作为输入,并在内存中更新正在运行的内核。在系统最初启动之前不需要做任何准备(例如,运行内核不需要特别编译)。为了生成更新,Ksplice 必须确定内核中哪些代码已被源代码补丁更改。Ksplice 在 ELF 对象代码层执行此分析,而不是在 C 源代码层执行。
要应用补丁,Ksplice 首先冻结计算机的执行,以便它是唯一运行的程序。系统验证没有处理器正在执行将被修改的函数。Ksplice 修改已更改的函数的开头,使其指向这些函数的新的、更新的版本,并修改需要更改的内存中的数据和结构。最后,Ksplice 恢复每个处理器在离开时运行的位置。
(来自维基百科)

3
我相信他们有模拟器来进行测试,并且有热修补机制。请查看下面链接的文章 - 文章中对宇宙飞船设计有一个很好的概述。第5节讨论了计算机设备。

http://www.boulder.swri.edu/pkb/ssr/ssr-fountain.pdf

需要注意的是:

  • 冗余处理器
  • 通过上行链路卡进行命令切换,无需处理器帮助
  • 延迟时间规则

2
我没有参与过航天器的工作,但我所涉及的机器都是建立在稳定的空闲状态上的,因此可以短暂关闭机器以修补固件。那些能够容纳“在线”更新的系统都是由互动组件组成的,您可以将系统的一个部分关闭足够长的时间以更新它,而其他组件可以继续正常运行,因为它们可以容忍服务组件的临时停机。
一种方法是具有并行(冗余)功能,例如执行相同任务的并行机器,以便可以将进程路由到正在服务的机器周围。这种方法的好处是,您可以将其关闭更长时间进行更重要的服务,例如定期的硬件预防性维护。一旦具备了这种能力,支持固件补丁的停机时间就相当容易。

1
过去使用的方法之一是使用LISP。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接