创建于 2020年4月20日
1997年7月,NASA 的 Mars Pathfinder(火星探路者)在降落火星表面后出了这么一档子事儿,被称为“火星上人类的第一个BUG”。
当飞船开始采集气象数据的时候,飞船所使用的 vxWorks 操作系统挂起(hung)并开始不断地重启。
究其原因,这是一个实时操作系统的经典BUG:Priority Inversion(优先级反转)。
解决办法听上去很简单,工程师上传了一小段 C 语言程序给飞船,从而在运行时将优先级继承的互斥标志从 false 改为 true,但请注意这是二三十年前,距离地球差不多6000万公里。
(注:优先级继承指的是,一旦发现低优先级任务占用了高优先级任务的资源,便立刻将其优先级升为与被占用任务相同优先级,尽快执行完。)
那么到底是如何修复远在火星上的飞船软件呢?
火星探路者软件开发组组长 Glenn Reeves 说:
我们并没有使用 vxWorks shell 来变更飞船上的软件,虽然飞船上这个 shell 是可用的。飞船软件打补丁一般来说是发送了一个(通过 Diff 处理得到的)差量文件给飞船,飞船经过一系列校验之后修改软件(onboard copy)。
昀哥理解他们是这么做的,vxWorks 自带一个C语言解释器,它允许开发人员输入和执行 C 语言表达式来进行系统调试。工程师们决定开启这个特性,然后上传一小段 C 程序,在它解释并执行的时候就可以把优先级继承的互斥标志从 false 改为 true。
图 发现并修复了这个 BUG 的工程师 Glenn Reeves,他背后是火星探路者的复制品
Priority Inversion(优先级反转)是嵌入式实时系统里的一个经典的问题。
三个任务的优先级
有三个优先级不同的任务,A、B、C。A的优先级最高,B次之,C最低。其中A和C有共享的临界区。如果C已进入临界区,那么A在进入临界区之前,就会被阻塞。B有可能打断C而进入运行状态,这样C什么时候从临界区退出,就是一个未知的时间。A只有在C从临界区退出后才能被调度,A被阻塞的时间也是未知的。这样,低优先级的B先于高优先级的A被调度,优先级发生了逆转。
优先级反转原理图
这个问题在一般的操作系统里并不是一个严重的问题,最多A被多阻塞了一段时间。但是,在实时系统里面,如果一个任务在规定的时间里面没有被调度运行,系统就相当于失败了,可能引发系统崩溃。
这个BUG实际上在地球上做飞行前预检测试的时候已经发现了,但不幸的是,BUG等级被标注为低优先级,于是带伤上了火星……
我们从中得到的经验教训是:
只有对实际系统行为(即使它在火星)能做端到端的详细追踪(现场调试和日志下载),才能捕获、识别并解决错误。一个不能追踪和调试的黑盒子(即使它在你所在的城市),跟肉包子打狗没有区别。你的设备自带远程调试(甚至是远程镜像工具,就像我们的IoT平台太空桥所做到的一样)是非常重要的。如果不能即时修改系统,则万事皆休,尤其是在2020年,你还能随随便便去一个城市、进入保卫森严的园区或办公楼吗?
火星救援剧照
-END-