神译局是36氪旗下编译团队,关注科技、商业、职场、生活等领域,重点介绍国外的新技术、新观点、新风向。
编者按:天天跟电脑、手机的我们对操作系统自然不陌生。Windows、macOS、Linux、Android、iOS……,这些操作系统大部分人都耳熟能详。可是,你知道承担探索太空任务的那些航天器用的是什么操作系统吗?你知道火星探路者为什么差一点出师未捷身先死吗?科技作者Jacek Krywko为我们揭秘在太空中运行的操作系统。原文标题为:Definitely not Windows 95: What operating systems keep things running in space?篇幅关系,我们分两部分刊出,此为第一部分。
欧洲航天局的“太阳轨道器”进入水星轨道后将要面对太阳的炙烤。
划重点:
太空级软件必须是完全可预测的,并且必须在特定的期限内执行完毕
商用实时操作系统VxWorks承担了NASA的多项任务
一个罕见的优先级倒置问题导致火星探路者反复重启
欧洲航天局最近发射的太阳轨道器将要在太阳系最不受欢迎的地方之一:太阳那里度过几年的时间。在执行任务期间,太阳轨道器跟太阳的距离要比比水星还要接近1000万公里。提醒你一下,水星离太阳已经够近了,近到其朝向太阳的一面的温度可达450°C。
为了能够承受这种温度,太阳轨道器得靠设计复杂的隔热板。不过,这个隔热板只有在直面太阳的时候才能保护该航天器。因此,欧洲航天局给太阳能轨道器开发了一个实时操作系统(RTOS),这个操作系统可以在非常严苛的条件下运行。允许与太阳的最大偏离点只有6.5度。任何超过2.3度的偏离点都只能在很短的时间内才可以接受。当出现问题并检测到危险的航迹偏离时,太阳轨道器的反应时间只有50秒。
欧洲航天局飞行软件系统部的负责人Maria Hernek说:“我们对这项任务的要求非常苛刻。通常情况下,重启这样的平台大概需要40秒钟。然后我们总共有50秒钟的时间来查找问题、进行隔离、重新运行系统并采取恢复措施。”
我再重复一遍:这套操作系统是在太空上运行的,需要在50秒钟之内远程重启并恢复完毕。否则的话,太阳轨道飞行器就会被烤焦。
为了应对如此没有商量的时限,像太阳轨道器这样的航天器几乎总是由实时操作系统操纵的,其运行方式跟你我的普通笔记本电脑上面的那种完全不同。我们判断Windows或macOS的标准非常简单。执行计算,如果计算结果正确,则认为任务正确完成。太空中使用的操作系统至少要增加一项核心标准:计算必须在严格指定的时限内正确完成。如果及时完成,则任务将视为失败并终止。在航天飞行里面,错过截止期限往往意味着航天器已经变成了火球或误入到错误的轨道。进一步处理此类任务将变得毫无意义。一切都必须遵循非常精确的时间限定。
用时钟来测量的时间被分成单数的滴答时间。为了简化,太空操作系统一般都是设计成每一项任务都在设定数量的分配好的滴答时间内执行完毕的。从传感器上传数据可能需要三个滴答时间;启动引擎需要四个滴答时间等。每一项可能的任务都会分配有特定的优先级,这样优先级较高的任务可以先于优先级较低的任务执行。通过这种方式,软件设计人员就可以准确地知道在任何给定场景下要执行的任务是什么,以及完成此任务需要花费多少时间。
为了跟我们所知道的操作系统进行比较,只需看看现代智能手机之间任何的速度对比即可。在这个有EverythingApplePro制作的评测视频当中,在一些热门app的打开速度上,iPhone XS Max和三星S10 Plus几乎是齐头并进的。在测试之前,两部手机都要重新启动,并清理缓存。三星打开所有app所用时间是2分30秒,而iPhone用时为2分54秒内。在第二轮测试中,所有app都将在没有重新启动或清除RAM的情况关闭并再次打开。由于app仍驻留RAM,所以三星在46秒内完成了打开,而iPhone用时为42秒。第一次测试和第二次测试的用时相差两分钟之多。但是,如果手机跑的是用于太空飞行的实时操作系统的话,则不管试多少次,打开这些app所花费的时间都将完全相同,最低可仅为一毫秒。
除了时间以外,太空操作系统还有更多的绝招。实时操作是一回事,确定性则是另一回事。如果你能设法说服Craig Federighi(苹果负责软件工程的高级副总裁)参与当中的某项速度评测,赋予其iPhone的完全访问权限,并要求他准确预测出这部iPhone完成测试所需的时间的话,他大概是不知道的。当然,他可能会说“很快”或者“够快”,甚至“非常的快”,但就没法再具体了。iOS和Android都不是确定性系统。可能会影响最终速度的因素太多了,以至于几乎不可能做出如此精确的预测。但是,如果手机跑的是太空级操作系统的话,则有权访问系统的工程师会确切知道是什么原因导致了执行序列是这样子的,并可以计算出完成任何给定任务所需的确切时间。太空级软件必须是完全可预测的,并且必须在特定的期限内执行完毕。
在阿波罗登月时代,操作系统是为每项任务量身定制的。当然,其中一些代码会被重用——比方说,为阿波罗计划制作的部分软件后来沿用到太空实验室(Skylab)计划和航天飞机(Shuttle)计划。但是在大多数情况下,操作系统都必须从头写起。
一次小小的重启
在那次著名的登陆行动中,巴斯(Buzz Aldrin)和尼尔·阿姆斯特朗(Neil Armstrong)把会合雷达天线留在了月球上面,并将其指向绕月飞行的阿波罗指挥舱。对于登陆者来说,这是一项安全措施,以便需要中止着陆时自己能够知道指挥舱在哪里。但后来的结果是雷达天线不断向计算机传输数据,导致AGC很快就把内存耗光了。臭名昭著的1201和1202错误其实就是指没有空闲的磁心或存储磁心,以及没有空闲的矢量聚集区的意思。内存不足导致登陆程序无法按时执行完毕,这又导致了计算机重复启动。尽管如此,幸好操作系统内置了安全措施,因此在重新启动过程中重要的导航数据并没有丢失——着陆可以按计划进行。操作系统只需从上次中断的位置继续运行计划的任务即可。
最终,美国宇航局选定了来自加州阿拉米达的WindRiver作为操作系统的解决方案。1987年,WindRiver推出了套装商用实时操作系统VxWorks 。虽然VxWorks并不是同类系统的第一个,但它很快成为部署最广泛的实时操统,这意味着VxWorks很快就被NASA计划设计师注意到了。
VxWorks执行的第一项飞行任务是克莱芒蒂娜环月轨道探测器(Clementine Moon),也被叫做深空计划科学实验(Deep Space Program Science Experiment)。早在1990年代初期,克莱芒蒂娜就标志着NASA已从类似阿波罗计划这样的庞然大物脱身出来了。一切都应该是精简的、研发周期短并且预算紧凑的。因此,采用VxWorks就成了克莱芒蒂娜探测器的设计选择之一,并且鉴于该系统给人留下了足够好的印象,后来它又获得了第二次飞行机会,成为了是火星探路者(Mars Pathfinder)计划的选择。
但是,对于这个RTOS来说,并非一切都是美好的。一个bug(优先级反转问题)给NASA的地面控制团队造成了很多麻烦。在着陆后不久,探路者的系统在没有明显原因的情况下开始重启,此事延缓了将收集到的数据传输回地球的速度。找到问题用了三周的时间,解决问题又花了18个小时。事实证明,这个问题根植于VxWorks的机制当中。
VxWorks的核心是wind微内核。它的任务是管理系统内所运行的应用程序与硬件之间的所有交互。在VxWorks里面,微内核负责用256个优先级对任务进行。所有任务之间的通信均支持抢占式和非抢占式循环调度。
系统中的任务可以处于这四种状态之一。“就绪”状态,即任务启动时的状态。然后,任务既可以运行直至完成,或者也可以给它分配一定的运行时间。当任务被另一个具有更高优先级的任务抢占时,或者当给它分配的滴答时间用完时,任务就进入到“阻塞”状态。第三种选项是“延迟”状态。当任务等待执行作业所需要的资源(也许是从传感器获取数据样本)时,就是被延迟了。延迟总是由独立于处理程序运行的计时器(通常是始终由内核维护的滴答计数器)来计算。当此类延迟超过某些设定值时,系统会认为可能的确发生了某种错误并开始重新引导。最后,还有第四种“挂起”状态,在该状态下,任务的上下文寄存器在系统停下来进行调试时会被保存下来。
VxWorks的任务间通信可以通过两种方式完成,要么通过可让任务交换数据的消息传递服务,也可以通过信号量来完成。信号量是用于确保任务在需要时互锁或同步的变量。VxWorks有两种信号量。第一种是二进制信号量,有两个值:“full”或“empty”。Full信号量对任务来说代表可用,而Empty信号量代表不可用。任务启动时,会取可用信号量,使其对于其他任务来说为“empty”或不可用。当任务完成执行时,它会放弃该信号量,从而令其对其他任务可用。
这种二进制的信号量是用来对不同的任务进行同步或者互锁。“信号量”这个名字有着铁路方面的内涵,我们不妨打个比方:想象一下,有两列需要在某个时间会合来交换货物的火车。在VxWorks这里,需要提货的火车会创建一个标记为空的信号灯,并将其交给目前正在运送该货物的火车。一旦载有货物的列车来到交换点将其卸货,该列车就会释放这个信号灯,让别人再来拿。一旦信号灯可用时第一列火车(创建信号灯的那趟列车)会收到通知,然后过来取货。
除了二进制的信号量以外,VxWorks还有第二种类型的信号量,叫做互斥或“mutex”信号量。这种类型的信号量可以让任务独占使用资源。其主要区别在于信号量的初始化方式。二进制信号创建的始终都是empty。互斥信号量创建的时候始终都是full。任务创建一个为full的信号量并马上取走,从而使得该信号量对其他任务不可用,直到其做完正在做的事情为止。此类信号量通常用于访问通信硬件。任务需要使用此类设备(比方说信息总线)直到数据传输完毕。在完成传输之前终止传输是毫无意义的,所以就需要有互斥信号量。
这种设置听起来似乎很聪明吧?的确如此。这套信号量系统是VxWorks的专利,也是这套系统的卖点之一。但是火星探路者在“红色星球”上面刚开始的那几周时间里,这套RTOS可是每况愈下的。
火星探路者号上的“信息总线”是一个共享存储器,用来给着陆器的不同组件之间传递数据。可以预见,这个地方必然是被互斥信号量锁定的资源。结果表明,导致神秘的重启涉及到了三任务。第一个是一个高优先级的任务,负责的是管理信息总线的操作。第二个任务是低优先级的任务,该任务有时需要获取信息总线互斥信号量来共享气象数据。而第三个元凶是中优先级的通讯任务。
这套系统本该是要这样工作的:对气象数据收集任务原来的预期是应该很少会占用信息总线互斥锁。在极少数情况下,当气象数据收集任务在运行时,信息总线管理任务也会被调度要运行,这时候优先级较高的任务会尝试控制同一个互斥锁——所以该任务最终会被阻塞,直到优先级较低的气象数据已写入总线。到目前为止,一切都还好,因为数据传输本该是从开始执行到结束。但是这时候第三项中等优先级的通信任务又闯了进来并造成了麻烦。
麻烦在于,在低优先级的气象任务导致高优先级总线管理任务被阻塞后,一系列不大可能发生的事件导致了中优先级的任务的运行。发生这种情况只有一瞬间的机会窗口,但是一旦发生时,中优先级任务就会优先于低优先级任务执行。在这种情况下,中断的气象数据收集没法做的众多事情之一就包括将互斥信号量释放给高优先级的总线管理任务。其结果是,中优先级任务间接阻塞了高优先级任务的运行,从而造成了优先级倒置。当然,这会导致总线管理任务进入延迟状态。而一旦内核的独立计时器确定重要线程未按计划运行时,它就会认为出问题了,然后发起完全重启。
这样的重启在两周之内出现了5、6次,不过VxWorks和它的设计最终并不是要归咎的对象。系统可以用一种叫做“优先级继承”的花招来处理此类问题,也就是让低优先级的任务暂时篡夺自己阻塞的另一优先级较高的任务的互斥锁。如果火星探路者的优先级继承起作用的话,气象数据收集任务会在总线管理任务在等待信号量时会篡夺其优先级。反过来,这又会阻止中优先级的通信任务抢占互斥锁。实现这一点要做的就只有一件事:在启动之前打开优先级继承选项。
所以,归根结底,火星探路者的问题是人为错误。所以VxWorks是无罪的,并且此后几乎所有登陆火星的探测器都有一颗VxWorks之心。在成为地球上部署最广泛的RTOS仅仅几十年之后,它也成为了那颗红色星球上最受欢迎的操作系统。
译者:boxi。