編者按: C語言是開發(fā)嵌入式應用的主要工具,然而C語言并非是專門為嵌入式系統(tǒng)設計,相當多的嵌入式系統(tǒng)較一般計算機系統(tǒng)對軟件安全性有更苛刻的要求。1998年,MISRA指出,一些在C看來可以接受,卻存在安全隱患的地方有127處之多。2004年,MISRA對C的限制增加到141條。
嵌入式系統(tǒng)應用工程師借用計算機專家創(chuàng)建的C語言,使嵌入式系統(tǒng)應用得以飛速發(fā)展,而MISRAC是嵌入式系統(tǒng)應用工程師對C語言嵌入式應用做出的貢獻。如今MISRA C已經(jīng)被越來越多的企業(yè)接受,成為用于嵌入式系統(tǒng)的C語言標準,特別是對安全性要求極高的嵌入式系統(tǒng),軟件應符合MISRA標準。
從本期開始,本刊將分6期,與讀者共同學習MISRAC。
第一講:“‘安全第一’的C語言編程規(guī)范”,簡述MISRAC的概況。
第二講:“跨越數(shù)據(jù)類型的重重陷阱”,介紹規(guī)范的數(shù)據(jù)定義和操作方式,重點在隱式數(shù)據(jù)類型轉換中的問題。
第三講:“指針、結構體、聯(lián)合體的安全規(guī)范”,解析如何安全而高效地應用指針、結構體和聯(lián)合體。
第四講:“防范表達式的失控”,剖析MISRAC中關于表達式、函數(shù)聲明和定義等的不良使用習慣,最大限度地減小各類潛在錯誤。
第五講:“準確的程序流控制”,表述C語言中控制表達式和程序流控制的規(guī)范做法。
第六講:“構建安全的編譯環(huán)境”,講解與編譯器相關的規(guī)范編寫方式,避免來自編譯器的隱患。
C/C++語言無疑是當今嵌入式開發(fā)中最為常見的語言。早期的嵌入式程序大都是用匯編語言開發(fā)的,但人們很快就意識到匯編語言所帶來的問題——難移植、難復用、難維護和可讀性極差。很多程序會因為當初開發(fā)人員的離開而必須重新編寫,許多程序員甚至連他們自己幾個月前寫成的代碼都看不懂。C/C++語言恰恰可以解決這些問題。作為一種相對“低級”的高級語言,C/C++語言能夠讓嵌入式程序員更自由地控制底層硬件,同時享受高級語言帶來的便利。對于C語言和C++語言,很多的程序員會選擇C語言,而避開龐大復雜的C++語言。這是很容易理解的——C語言寫成的代碼量比C++語言的更小些,執(zhí)行效率也更高。
對于程序員來說,能工作的代碼并不等于“好”的代碼!昂谩贝a的指標很多,包括易讀、易維護、易移植和可靠等。其中,可靠性對嵌入式系統(tǒng)非常重要,尤其是在那些對安全性要求很高的系統(tǒng)中,如飛行器、汽車和工業(yè)控制中。這些系統(tǒng)的特點是:只要工作稍有偏差,就有可能造成重大損失或者人員傷亡。一個不容易出錯的系統(tǒng),除了要有很好的硬件設計(如電磁兼容性),還要有很健壯或者說“安全”的程序。
然而,很少有程序員知道什么樣的程序是安全的程序。很多程序只是表面上可以干活,還存在著大量的隱患。當然,這其中也有C語言自身的原因。因為C語言是一門難以掌握的語言,其靈活的編程方式和語法規(guī)則對于一個新手來說很可能會成為機關重重的陷阱。同時,C語言的定義還并不完全,即使是國際通用的C語言標準,也還存在著很多未完全定義的地方。要求所有的嵌入式程序員都成為C語言專家,避開所有可能帶來危險的編程方式,是不現(xiàn)實的。最好的方法是有一個針對安全性的C語言編程規(guī)范,告訴程序員該如何做。
1 MISRAC規(guī)范
1994年,在英國成立了一個叫做汽車工業(yè)軟件可靠性聯(lián)合會(The Motor Industry Software Reliability Association,以下簡稱MISRA)的組織。它是致力于協(xié)助汽車廠商開發(fā)安全可靠的軟件的跨國協(xié)會,其成員包括:AB汽車電子、羅孚汽車、賓利汽車、福特汽車、捷豹汽車、路虎公司、Lotus公司、MIRA公司、Ricardo公司、TRW汽車電子、利茲大學和福特VISTEON汽車系統(tǒng)公司。
經(jīng)過了四年的研究和準備,MISRA于1998年發(fā)布了一個針對汽車工業(yè)軟件安全性的C語言編程規(guī)范——《汽車專用軟件的C語言編程指南》(Guidelines for the Use of the C Language in Vehicle Based Software),共有127條規(guī)則,稱為MISRAC:1998。
C語言并不乏國際標準。國際標準化組織(International Organization of Standardization,簡稱ISO)的“標準C語言”經(jīng)歷了從C90、C96到C99的變動。但是,嵌入式程序員很難將ISO標準當作編寫安全代碼的規(guī)范。一是因為標準C語言并不是針對代碼安全的,也并不是專門為嵌入式應用設計的;二是因為“標準C語言”太龐大了,很難操作。MISRAC:1998規(guī)范的產生恰恰彌補了這方面的空白。
隨著很多汽車廠商開始接受MISRAC編程規(guī)范,MISRAC:1998也成為汽車工業(yè)中最為著名的有關安全性的C語言規(guī)范。2004年,MISRA出版了該規(guī)范的新版本——MISRAC:2004。在新版本中,還將面向的對象由汽車工業(yè)擴大到所有的高安全性要求(Critical)系統(tǒng)。在MISRAC:2004中,共有強制規(guī)則121條,推薦規(guī)則20條,并刪除了15條舊規(guī)則。任何符合MISRAC:2004編程規(guī)范的代碼都應該嚴格的遵循121條強制規(guī)則的要求,并應該在條件允許的情況下盡可能符合20條推薦規(guī)則。
MISRAC:2004將其141條規(guī)則分為21個類別,每一條規(guī)則對應一條編程準則。詳細情況如表1所列。
表1MISRAC:2004規(guī)則分類

最初,MISRAC:1998編程規(guī)范的建立是為了增強汽車工業(yè)軟件的安全性?赡茉斐善囀鹿实脑蛴泻芏啵鐖D1所示,設計和制造時埋下的隱患約占總數(shù)的15%,其中也包括軟件的設計和制造。MISRAC:1998就是為了減小這部分隱患而制定的。
MISRAC編程規(guī)范的推出迎合了很多汽車廠商的需要,因為一旦廠商在程序設計上出現(xiàn)了問題,用來補救的費用將相當可觀。1999年7月22日,通用汽車公司(General Motors)就曾經(jīng)因為其軟件設計上的一個問題,被迫召回350萬輛已經(jīng)出廠的汽車,損失之大可想而知。
MISRAC規(guī)范不僅在汽車工業(yè)開始普及,也同時影響到了嵌入式開發(fā)的其他方向。嵌入式實時操作系統(tǒng)μC/OSII的2.52版本雖然已經(jīng)于2000年通過了美國航空管理局(FAA)的安全認證,但2003年作者就根據(jù)MISRAC:1998規(guī)范又對源碼做了相應的修改,如將
if ((pevent->OSEventTbl[y] &= ~bitx) == 0) {
/*… */
}
的寫法,改寫成
pevent->OSEventTbl[y] &= ~bitx;
if (pevent->OSEventTbl[y] == 0) {
/*… */
}
發(fā)布了2.62的新版本,并宣稱其源代碼99%符合MISRAC:1998規(guī)范。
一個程序能夠符合MISRAC編程規(guī)范,不僅需要程序員按照規(guī)范編程,編譯器也需要對所編譯的代碼進行規(guī)則檢查,F(xiàn)在,很多編譯器開發(fā)商都對MISRAC規(guī)范有了支持,比如IAR的編譯器就提供了對MISRAC:1998規(guī)范127條規(guī)則的檢查功能。
2 MISRAC對安全性的理解
MISRAC:2004的專家們大都來自于軟件工業(yè)或者汽車工業(yè)的知名公司,規(guī)范的制定不僅僅像過去一樣局限于汽車工業(yè)的C語言編程,同時還涵蓋了其他高安全性系統(tǒng)。





