推測“好奇號”火星車和它搭載的軟件
首先來些基礎的。“好奇號”火星車使用的是核動力,它能持續的受控的方式提供給火星車能量。這個能量源同時還要負責平時對火星車進行加熱——這是在火星表面極端天氣環境下對火星車的必要保障。
“好 奇號”基本上是自主控制的。它發送一條信息可能要用幾分鐘到幾小時的時間,你只能在火星上一天里的有限時間段內給它發送信息。“好奇號”自己可 以和地球通話,但這條線路速度很慢。它也可以通過圍繞火星飛行的人造衛星進行通信,把衛星作為上行線路中繼,這樣更快。這種情況表明:火星車必須要能自主 行動。我們不能讓一個人坐在地球上的某個椅子里拿著操縱桿來指導它。
“好奇號”火星車上安裝有兩個完全一樣的計算機。我們注意到美國宇航 局正是按照Joe Armstrong(Erlang編程語言的創造人)的話做的:“要想獲得一個可信賴的系統,你需要兩臺計算機”。一個一直處于休眠狀態,一旦另一個由于 異常情況死機,它可以隨時受命接管系統。這樣的做法在Erlang語言系統里、在OpenBSD PF防火墻等其它軟件里都是很典型的接管方案。“好奇號”上使用的計算機是BAE systems RAD750。處理器是PowerPC ISA,速度非常的快。200百萬赫茲, 150或250納米 的制造工藝,它工作時對能允許的溫度范圍的表現非常優秀。它是經過抗輻射加固的,能經受相當強的輻射侵襲。內存也是抗輻射的。“好奇號”上的計算機里的每 個硬件都不是隨隨便便一個東西能勝任的。
“好奇號”的操作系統使用的是VxWorks。它屬于標準的的微內核系統。保守的估計,它的內核代碼應該少于1萬行,而且經過了嚴格的測試。也就是說,這個內核接近零bug。它的一個主要特征就是隔離。火星車上的各個模塊都是相互隔離的。有些子系統對火星車的生命起著至關重要的作用,而另外一些只是用于科學觀察的設備。所以,我們可以肯定這樣一個事實,“好奇號”上的250萬行代碼中,只有一部分代碼是深度測試杜絕了bug的。車上的有些程序并不是生命必須的。
美國宇航局使用了各種辦法來確保代碼質量。例如,遞歸調用是要求避免的,這是這因為C語言編譯器不能保證遞歸堆棧不被撐破。循環要確保有終止點,這 通過一個靜態分析器來發現這些問題。所有的內存使用都幾乎是靜態分配的,這樣避免了突然的內存收集產生的混亂和不可預知的性能問題。我們還可以發現訊息傳遞(Message Passing)作為子系統間的消息傳遞方式在火星車是被當作了***。不存在互斥,不存在軟件事務性內存。同樣,隔離概念也是編碼指導原則上的一部分。通過對內存進行保護和數據的單一歸屬關系,子系統之間就很難影響對方。Erlang程序員都很習慣這樣的做法。
“探路者”號火星車
當年的“探路者”號火星車的架構設計事實上也跟Erlang語言系統的理念相似。它有用于傳遞消息的“組件”。組件只在接收消息時才等待,發送消息的都是無返回值的函數。它們接受消息采用的是單事件循環,這跟Erlang語言中的 gen_server 工作方式很相似。不同的模塊間通過某種協議傳遞消息進行通信,你可以訪問其它模塊使用的內存,但按照JPL編碼指導原則,這種做法是要避免的。這跟 Erlang語言有所不同,Erlang語言完全禁止這樣操作。火星探測漫游者(勇氣號和機遇號)擁有更多的組件,但軟件基礎上相同的。“好奇號”也不例 外。它本質上是在老的軟件上改造出來的。系統中的線程數有大幾百個,這***的和一個類似的如此規模的Erlang語言系統中的線程數相匹配。
機遇號火星車
在 “好奇號”上,他們增加了“組件”的概念,組件由一組組的模塊構成,以此用來控制復雜度。因為有兩臺計算機做冗余,很多子系統為了系統的穩固也是 冗余的,組件的概念也是處理這些情況需要的。有趣的是,Erlang語言的設計者也看到了這一點,只是在Erlang里被叫做Applictions。
對 函數恒量的校驗。輸入參數必須要滿足前置條件。后置條件約束返回值。各種恒量必須滿足這些條件。Erlang程序員熟悉這種做法。有趣的是,“好 奇號”上的每個函數的長度限制在60行以內,這樣它們可以被打印到單張紙上。Erlang程序員也喜歡簡短的函數體,但沒有這種限制。但都是為了讓代碼簡 單。讓代碼易于理解。
勇氣號火星車
還有另外一個有趣的事情,在過去,有個火星車發生過優先級顛倒的問題。他們在調試控制臺里向火星車注入了一段糾正信息挽救了火星車。這也跟 Erlang語言系統里經常使用的方法相似。我們可以對運行中的系統進行修改,隨時對系統進行升級和改造。我們對運行中的系統進行監控,確保它的運行狀態 跟我們期望的一樣。這種對系統進行熱修復的能力非常的有用。當然,這種開發是配合了大量的跟蹤和分析——例如使用Erlang QuickCheck/PropEr,錯誤記錄以及跟蹤工具。
很明顯,Erlang語言系統的很多特征都跟火星車上的系統吻合。但我并不認 為這是巧合。各種軟件有自己不同的屬性特征——火星車屬于硬實時 (hard realtime)環境,Erlang語言系統是軟實時環境。但大體上,寫出健壯系統的條件是你需要隔離系統中的各個部分。這值得思考,看起來這種方式好用。這些對于高可靠性系統來說都是的重要的特征。也許比靜態類型校驗還要重要。
總 結來看,對于火星車上的所有代碼,我們也許并不必保障所有代碼都達到***級別的安全。我們可以把不同的模塊進行隔離測試,對它們實施不同等級的正 確性檢查。換句話說,我可以通過精心的設計來控制錯誤和管理風險。因此,對于某些模塊,我們可以承認它們可能存在某些錯誤。如果上行通信中繼壞了,我們可 以重啟機器,這樣來恢復它。如果這樣不行,我們還有一個冗余的上行通信通道直接和地球通信,只是速度慢些——但可以替代另外一個通道。這種架構意味著只有 多個組件同時失敗時才能導致任務無法完成。模塊出錯,重啟,恢復,然后就可繼續拍攝圖片。這種設計的基本原理是非常可靠的,也許需要根據情況做一些小的調 整。畢竟它是經過了另外3個火星車的嚴格考驗上發展出來的。
跟Erlang語言理念不相同的部分跟所對應的硬實時和軟實時環境有關。在 Erlang語言系統中我們可以暫緩服務。雖然不好,但可以這么干。在火 星車上,這會成為災難。在飛行控制系統中尤其是這樣。如果火箭啟動晚了,你的麻煩就大了。這就是為什么“好奇號”上要使用靜態分配內存和固定堆棧大小,而 不是使用動態分配的原因。這同樣也是他們不喜歡遞歸的原因。而在Erlang語言系統里,我們不鼓勵通過手動管理內存。我們對tail調用做了革命性的優 化,所以我們可以放心的使用它。
長話短說——“好奇號”火星車的軟件在某些特征上跟Erlang語言系統在架構上非常是相似。這些特征是一個健壯的軟件系統的基本特征嗎?
【編輯推薦】