創建於 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-