1997年,美国发射的探测器“探路者号”在火星上究竟发生了什么?

1997年,美国发射的火星车“探路者(Pathfinder)号”成功着陆火星,当日官方宣告此次着陆“完美无瑕”,探路者号开始收集和传输大量火星数据回地球。

如今网络上很多流行的火星图片,很多都是由探路者号拍摄的。

“并不完美”的火星探路者号

然而,在随后的几天里,探路者号在收集和传输气象数据时,开始出现系统重启的情况,而且每一次重启都会丢失一些数据。一开始,研究小组并不能确定这些异常是什么原因导致的,媒体以“软件故障”,以及“系统同时运行过多任务,负载太大”等术语报道这些故障。

研究小组认真排查问题后,在IEEE实时系统研讨会上,WindRiver(开发了VXWorks系统) 系统首席技术官 David Wilner 较为详细的介绍了探路者号出现故障的原因。

探路者号使用了 VXWorks 作为底层的实时嵌入式系统内核,VXWorks 支持多线程编程,并且提供了线程的优先级抢占调度机制。探路者号内部的任务是以线程的形式运行的,并且各个任务根据重要程度被分配了不同的优先级。

探路者号系统包含一个“信息总线”,可以把它看作是一个共享的内存区域,用于在系统内部不同组件之间传递信息。

鉴于“信息总线”非常重要,所以管理总线的任务以高优先级频繁运行,将数据传输到各个组件。当然了,对于组件们来说,总线是共享资源,因此系统对总线的访问做了互斥同步。

探路者号出现故障时,正在执行的气象数据采集任务则是一个不常运行的任务,所以它的线程优先级较低。不过,气象数据采集任务作为系统的一个组件,也是要使用“信息总线”的,它在需要传输数据时,会获取互斥体,并将数据写入总线,然后释放互斥体。

如果信息总线持有互斥锁时被中断打断,进入操作系统重新调度,之后又尝试请求同一个互斥锁以取回气象数据采集任务的数据并发送时,那么C语言程序将被阻塞等到气象数据采集任务释放互斥体。探路者号系统还包含一个中等优先级的通信任务。

大多数情况下,上述线程工作配合的很好。但是,中断随时可能发生,因此系统还是有可能会出现这种情况:(高优先级)信息总线管理线程被阻塞,等待(低优先级)气象数据线程释放互斥锁时,(中等优先级)通信任务在这一短时间间隙被调度。

在这种情况下,长时间运行的中等优先级的通信任务将阻断比其优先级低的气象数据采集任务,导致气象数据采集任务无法运行,也就可能导致其无法释放互斥锁,进而导致高优先级的信息总线管理线程永远阻塞下去。

过一段时间后,探路者号的看门狗程序注意到信息总线任务有一段时间没有运行,就断定系统发生了严重错误,因此会重启整个系统。

这个场景其实就是“优先级反转”的经典案例,关于“优先级反转”,更详细的讨论可以参考我之前的文章《》。

研究小组如何排查和修复故障?

VXWorks 可以以一种特殊模式运行,在该模式下,它可以跟踪系统事件,进行上下文切换,以及同步对象和使用终端。

在发现探路者号的故障后,工程师们不断的调试,在实验室中精确的复制了一份探路者号的系统,并且开启了VXWorks的跟踪机制,开始尝试他们推测的可能错误。

工程师们夜以继日的排查,经常通宵工作。在几天后的黎明,当工程师都回家时,还有一个工程师终于重现了一次系统重启的bug。后来,工程师们根据VXWorks跟踪得到的信息,推测出探路者号是因为“优先级反转”导致的故障。

工程师们是如何解决故障的?

当在 VXWorks 中创建一个互斥体时,互斥对象接收一个布尔类型参数,该参数用于指定互斥对象是否应该执行优先级继承。

探路者号系统传递给互斥体对象的参数是 off,也即不继承优先级。事实上,如果将该参数改为 on,则低优先级的气象数据采集线程将继承阻塞的信息总线管理线程的高优先级,从而使其优先于中等优先级的通信任务,就能阻止系统重启。

VXWorks 包含一个C语言解释器,它允许开发人员在系统调试期间输入要动态执行的C语言表示语句和函数,研究小组的工程师通过编码约定,将传递给互斥体对象的参数存储在全局变量中,这些变量的地址包含在启动软件中的符号表中,可供C语言解释器使用。

这样一来,工程师们将修改后的简短C语言程序上传到探路者号,当这段C语言程序执行时,它会将传递给互斥对象的参数由 off 改为 on。

教训

首先,对于“优先级反转”这类隐藏很深的bug,“黑盒测试”基本很难排查。只有对实际的系统行为做详细跟踪分析,才有可能捕获错误并解决。

其次,将“调试”手段保留在系统中是正确的,否则也很难定位错误,并纠正错误。

最后,研究小组的分析:“信息总线任务运行频率很高,时间很关键,所以我们不该再其中花费额外的时间来执行优先级继承”是完全错误的。即使系统对时效要求很高,为了保证稳定性和可靠性,哪怕多一些时间开销也是应该接受的。

C语言程序中漏洞的“人为”因素

在后来的报告中,探路者号研究小组的工程师后来承认,在发射前几个月的测试中,已经发生过一两次系统重启。但是工程师们在软件上后来没有再重现“重启”错误,在 dead line 的压力下,智能将这样的错误归结为“可能是硬件故障引起的”理由,认为这样的错误并不重要。

阅读更多:   C语言
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif