盧利勇 孫壽龍
(北京全路通信信號研究設計院有限公司,北京 100073)

盧利勇,男,碩士畢業于蘭州交通大學,工程師。主要研究方向包括嵌入式系統設計、計算機聯鎖系統開發,曾參與DS6-60故障安全平臺、全電子計算機聯鎖項目。
隨著軌道交通系統的日新月異發展,軌道交通系統相關設備的需求也日益擴大。故障安全平臺,不僅可以應用到國有鐵路的車站聯鎖控制,還可以應用到城市軌道交通信號控制系統中,如計算機聯鎖系統、區域控制中心等,還可以作為CTCS-2或CTCS-3系統中的車站列控中心使用,具有廣闊的應用前景。
然而軌道交通系統作為大容量公共交通工具,其安全性直接關系到廣大乘客的生命安全。其中信號系統作為保證列車安全、正點、快捷、舒適、高密度不間斷運行的重要技術裝備,在軌道交通系統中有著舉足輕重的地位。因此,對信號系統其中的故障安全平臺的安全性提出更高的要求。
在研發中使用哪些安全防護技術更好、更有效,從而使故障安全平臺更加安全可靠,成為困擾眾多研發者的問題。
本文以DS6-60①DS6-60型故障安全平臺是北京全路通信信號研究設計院有限公司自主創新研發的一個符合歐洲鐵路安全標準的計算機聯鎖系統。該系統采用二乘二取二冗余結構設計, 系統中所有涉及到安全信息處理和傳輸的部件均按照“故障-安全”原則采取了2重系結構設計,滿足鐵路車站信號控制設備高可靠和高安全的使用要求。現已在全路大面積推廣。故障安全平臺為例,對二取二安全機制、工具安全性分析和防御性編程3種關鍵安全防護技術的使用進行闡述。
二取二防護機制能有效防止單點故障,二取二安全機制在實現上還需要注意些什么,下面結合一個例子來說明。

如圖1所示,圖1中執行模塊的設計,為了防止一個CPU發生故障,誤輸出,使用了雙CPU二取二協同輸出的方式,CPU1輸出動態脈沖碼,CPU2輸出靜態電平信號,只有當CPU1和CPU2都輸出時,執行模塊通過表決器最終才會輸出驅動信號。
下面設想幾種場景,分析基于以上設計,是否還有危險輸出。
1)場景1:CPU1故障一直輸出動態脈沖②CPU1為動態輸出,如果CPU1輸出動態脈沖表示系統本周期有輸出,如果CPU1輸出靜態電平表示系統本周期無輸出。。這時二取二已經失效,相當于只有CPU2控制輸出。
解決方法:如圖1中線2,CPU1回讀CPU2的輸出信號,CPU1每周期在輸出前,先要檢查CPU2的輸出狀態,只有CPU2有輸出,CPU1才輸出動態脈沖,否則CPU1不輸出。
2)場景2③每一種場景都是基于上一場景提出問題已解決,結構已完善的基礎上。:比較器故障。CPU1和CPU2都沒有輸出,通過比較器輸出了驅動信號,驅動繼電器誤動作。
解決方法:如圖1中線1。CPU2每周期都會通過檢測回讀電路獲得比較器后端的輸出,如果本周期CPU2沒有輸出,而比較器后端有輸出,CPU2經過過濾期④過濾期為系統可容忍的最大時間,由具體的系統功能確定該時間。后,做出相應的故障安全處理。
3)場景3:CPU2檢測回讀電路故障。比較器故障后,產生了誤輸出,由于檢測電路故障,不能及時發現。
解決方法:系統在沒有輸出的周期,產生時間較短、能量較弱的確保不會導致現場設備動作的測試輸出信號,這樣,在沒有輸出時,通過測試輸出信號,及時發現檢測回讀電路的狀態,一旦發現檢測回讀電路故障,立即做安全處理,確保不會誤輸出。

雙CPU同步是二取二實現的一個關鍵問題,如圖2所示,DS6-60邏輯部二取二硬件設計中,采用同一個時鐘源產生時鐘,然后經過同步中斷產生電路,產生固定周期的中斷信號,為雙CPU任務級同步提供硬件支持。為了防止時鐘源跑偏,每個CPU除了外部同步中斷計時,內部也有定時器計時,每周期開始要對外部同步中斷計時和內部定時器計時進行校準,確保內部和外部計時的一致性。
兩個CPU采用相同的輸入數據進行獨立運算,運算結果通過雙口RAM進行交互,比較一致時才可以對外輸出;如果不一致,系統退出控制,導向安全側,保證系統的高安全性。比較原理如圖3所示。

在軟件開發的不同階段中,工具對開發者都是有很多幫助的。
在開發DS6-60系統過程中,使用SVN做文檔和代碼管理,使用了Testbed 做靜態走查和單元測試,使用了ADS集成開發環境,在ARM芯片上完成調試和下載等。
根據EN50128對工具的分類,T1類工具為不產生任何對軟件執行代碼(包括數據)影響的工具;T2類工具為支持對設計或執行代碼進行測試或驗證功能,該類工具中的缺陷可能導致不能有效地發現設計或執行代碼的缺陷,但是該類工具不會直接在執行軟件中產生錯誤;T3類工具為產生對安全相關系統的執行代碼(包括數據)直接或間接有影響的輸出工具。
以上羅列的幾種工具,其中SVN為T1類,Testbed為T2類,ADS為T3類。T3類工具必須進行安全性分析,并針對其可能帶來的安全風險提供規避措施。
ADS帶來的風險如下。
1)ARM C編譯器和ARM C鏈接器生成的目標文件邏輯不正確(目標文件邏輯上不符合程序源代碼的描述)。
2)ARM C編譯器和ARM C鏈接器在生成的目標文件中人為地插入惡意代碼,導致目標程序運行不可靠或達到某些其他惡意目的。
3)AXD在將目標文件燒寫至ARM芯片時發生錯誤,芯片中運行的程序與目標文件邏輯上不一致。
1)使用強類型語言或非強類型語言的安全子集
在DS6-60中使用C語言做為編程語言。C語言屬于非強類型語言,很靈活,卻有很多陷阱。C語言有很多依賴于編譯器的未定義的行為。如:數據類型及對齊方式、數據在內存的儲存方式等。
SPSS21.0統計軟件分析數據,用χ2檢驗計數資料組間率,計數資料用例數[n(%)]表示,P<0.05為差異具統計意義。
* ADS開發環境C編譯器以上行為分析如表1所示。

表1 ARM C編譯器數據類型的大小和對齊
* ARM C編譯器既支持大端模式,也支持小端模式,默認為小端模式。
通過以上對編譯器某些行為的分析,故障安全平臺的軟件開發,在C語言的使用上盡可能少使用與編譯器相關的行為,使其盡可能的安全可控。如迫不得已使用時,應明確編譯器對應行為的處理方式,并應將其文檔化。如數據類型的轉換,必須強制轉換,而不是通過編譯器隱式轉換;如有可能會導致內存溢出的strcpy/memcpy等庫函數,在使用時需格外小心,保證不會發生內存溢出。在DS6-60開發中,使用符合MIRSA C 2004且對C語言有更多約束的C語言安全子集。
2)采取二取二的安全比較機制,雙CPU在運行中比較邏輯的輸入和輸出值,如不一致,做故障處理。
3)雙CPU采用不同編譯器,防止共模錯誤。
數據溢出、指針非法、關鍵數據被改寫這些安全性問題經常困擾著軟件開發工程師,一旦發生,排查問題需要花費很多的時間和精力。防御性編程的使用可以大大增加軟件設計的安全性。顧名思義,防御性編程是一種細致、謹慎的編程方法。防御性編程的目標是通過處理已知的由硬件隨機性故障或軟件系統性故障引起的軟件故障,從而提供軟件健壯性。
下面從兩個方面來說明防御性編程:一方面是故障檢測;另一方面是錯誤檢測。
Fun(UINT8_T * pSrc)
{
UINT8_T temp;
temp = g_num ;
…
}
在段代碼中,pSrc指針沒有任何防護,局部變量也未初始化,局部變量如果不做顯性的初始化,局部變量的初始值是不確定的,完全依賴于編譯器。關鍵全局變量g_num未做防護。
修改后的代碼如下。
Fun(const UINT8_T * pSrc)
{
/*參數合法性校驗*/
if(pSrc != NULL)
{
UINT8_T temp = 0U;/*無符號型的常量加U*/
/*關鍵全局變量合法性校驗*/
if (g_num <= MAX_NUM)/*MAX_NUM 為g_num的最大合法值*/
{
temp = g_num ;
…
}
else
{
…/*全局變量不合法故障處理*/
}
}
else
{
…/*參數不合法故障處理*/
}
}
這里說明一點,并不推薦對系統的所有全局數據進行合法性校驗,但是關鍵全局數據在使用前應加以校驗。當然故障檢測除了范圍的檢測,還有資源上的防護等。比如在軟件中對關鍵靜態變量做周期性的校驗,防止關鍵靜態數據被非法改寫。在多任務的程序設計中,應當慎用共享變量進行各任務間數據交換。因為CPU對多任務程序進行調度執行時可能造成數據不一致。確需使用共享變量時應當作為臨界資源保護起來,以控制對該臨界資源的互斥訪問。
比如操作系統與應用軟件之間的防護關系:一方面操作系統如何保護應用軟件,包括調度和內存等資源管理,并保證不同應用軟件運行之間不會沖突等;另一方面應用軟件故障/異常行為不會影響操作系統的正常工作。這些在設計階段都需要考慮。
這里所說的錯誤檢測專指檢測通信會話中出現的數據丟失或損壞。一般經常使用的檢測方法為:奇偶校驗位、校驗和、循環冗余校驗碼等。一般采用檢錯重發技術。
采用二取二安全機制時,需要考慮很多故障場景,以便實現真正意義上的二取二;工具安全性分析,不容易被重視,卻最終可能會導致故障安全平臺發生所謂的“詭異”問題,編譯器、鏈接器等工具可能帶來的風險需要增加防護;防御性編程可以提高軟件的健壯性,對于使用類似C語言的非強類型語言,建議在使用中對C語言的行為做出約束,使C語言的行為更加安全可控。
除了上述3種安全防護措施,在故障安全平臺研發中,可能還會用到其他的安全防護措施,系統根據自身的特點,選用適合本系統的安全防護技術,最終使故障安全平臺安全可靠的運行。
[1] EN50128:2011鐵路應用:通信、信號和處理系統 鐵路控制和防護系統用軟件[S].
[2] EN50129:2003鐵路應用:鐵路控制系統領域的安全相關電子系統[S].