| 編者按: C語(yǔ)言是開(kāi)發(fā)嵌入式應(yīng)用的主要工具,然而C語(yǔ)言并非是專門(mén)為嵌入式系統(tǒng)設(shè)計(jì),相當(dāng)多的嵌入式系統(tǒng)較一般計(jì)算機(jī)系統(tǒng)對(duì)軟件安全性有更苛刻的要求。1998年,MISRA指出,一些在C看來(lái)可以接受,卻存在安全隱患的地方有127處之多。2004年,MISRA對(duì)C的限制增加到141條。 嵌入式系統(tǒng)應(yīng)用工程師借用計(jì)算機(jī)專家創(chuàng)建的C語(yǔ)言,使嵌入式系統(tǒng)應(yīng)用得以飛速發(fā)展,而MISRAC是嵌入式系統(tǒng)應(yīng)用工程師對(duì)C語(yǔ)言嵌入式應(yīng)用做出的貢獻(xiàn)。如今MISRA C已經(jīng)被越來(lái)越多的企業(yè)接受,成為用于嵌入式系統(tǒng)的C語(yǔ)言標(biāo)準(zhǔn),特別是對(duì)安全性要求極高的嵌入式系統(tǒng),軟件應(yīng)符合MISRA標(biāo)準(zhǔn)。 從本期開(kāi)始,本刊將分6期,與讀者共同學(xué)習(xí)MISRAC。 第一講:“‘安全第一’的C語(yǔ)言編程規(guī)范”,簡(jiǎn)述MISRAC的概況。 第二講:“跨越數(shù)據(jù)類型的重重陷阱”,介紹規(guī)范的數(shù)據(jù)定義和操作方式,重點(diǎn)在隱式數(shù)據(jù)類型轉(zhuǎn)換中的問(wèn)題。 第三講:“指針、結(jié)構(gòu)體、聯(lián)合體的安全規(guī)范”,解析如何安全而高效地應(yīng)用指針、結(jié)構(gòu)體和聯(lián)合體。 第四講:“防范表達(dá)式的失控”,剖析MISRAC中關(guān)于表達(dá)式、函數(shù)聲明和定義等的不良使用習(xí)慣,最大限度地減小各類潛在錯(cuò)誤。 第五講:“準(zhǔn)確的程序流控制”,表述C語(yǔ)言中控制表達(dá)式和程序流控制的規(guī)范做法。 第六講:“構(gòu)建安全的編譯環(huán)境”,講解與編譯器相關(guān)的規(guī)范編寫(xiě)方式,避免來(lái)自編譯器的隱患。 C/C++語(yǔ)言無(wú)疑是當(dāng)今嵌入式開(kāi)發(fā)中最為常見(jiàn)的語(yǔ)言。早期的嵌入式程序大都是用匯編語(yǔ)言開(kāi)發(fā)的,但人們很快就意識(shí)到匯編語(yǔ)言所帶來(lái)的問(wèn)題——難移植、難復(fù)用、難維護(hù)和可讀性極差。很多程序會(huì)因?yàn)楫?dāng)初開(kāi)發(fā)人員的離開(kāi)而必須重新編寫(xiě),許多程序員甚至連他們自己幾個(gè)月前寫(xiě)成的代碼都看不懂。C/C++語(yǔ)言恰恰可以解決這些問(wèn)題。作為一種相對(duì)“低級(jí)”的高級(jí)語(yǔ)言,C/C++語(yǔ)言能夠讓嵌入式程序員更自由地控制底層硬件,同時(shí)享受高級(jí)語(yǔ)言帶來(lái)的便利。對(duì)于C語(yǔ)言和C++語(yǔ)言,很多的程序員會(huì)選擇C語(yǔ)言,而避開(kāi)龐大復(fù)雜的C++語(yǔ)言。這是很容易理解的——C語(yǔ)言寫(xiě)成的代碼量比C++語(yǔ)言的更小些,執(zhí)行效率也更高。 對(duì)于程序員來(lái)說(shuō),能工作的代碼并不等于“好”的代碼!昂谩贝a的指標(biāo)很多,包括易讀、易維護(hù)、易移植和可靠等。其中,可靠性對(duì)嵌入式系統(tǒng)非常重要,尤其是在那些對(duì)安全性要求很高的系統(tǒng)中,如飛行器、汽車(chē)和工業(yè)控制中。這些系統(tǒng)的特點(diǎn)是:只要工作稍有偏差,就有可能造成重大損失或者人員傷亡。一個(gè)不容易出錯(cuò)的系統(tǒng),除了要有很好的硬件設(shè)計(jì)(如電磁兼容性),還要有很健壯或者說(shuō)“安全”的程序。 然而,很少有程序員知道什么樣的程序是安全的程序。很多程序只是表面上可以干活,還存在著大量的隱患。當(dāng)然,這其中也有C語(yǔ)言自身的原因。因?yàn)镃語(yǔ)言是一門(mén)難以掌握的語(yǔ)言,其靈活的編程方式和語(yǔ)法規(guī)則對(duì)于一個(gè)新手來(lái)說(shuō)很可能會(huì)成為機(jī)關(guān)重重的陷阱。同時(shí),C語(yǔ)言的定義還并不完全,即使是國(guó)際通用的C語(yǔ)言標(biāo)準(zhǔn),也還存在著很多未完全定義的地方。要求所有的嵌入式程序員都成為C語(yǔ)言專家,避開(kāi)所有可能帶來(lái)危險(xiǎn)的編程方式,是不現(xiàn)實(shí)的。最好的方法是有一個(gè)針對(duì)安全性的C語(yǔ)言編程規(guī)范,告訴程序員該如何做。 1 MISRAC規(guī)范 1994年,在英國(guó)成立了一個(gè)叫做汽車(chē)工業(yè)軟件可靠性聯(lián)合會(huì)(The Motor Industry Software Reliability Association,以下簡(jiǎn)稱MISRA)的組織。它是致力于協(xié)助汽車(chē)廠商開(kāi)發(fā)安全可靠的軟件的跨國(guó)協(xié)會(huì),其成員包括:AB汽車(chē)電子、羅孚汽車(chē)、賓利汽車(chē)、福特汽車(chē)、捷豹汽車(chē)、路虎公司、Lotus公司、MIRA公司、Ricardo公司、TRW汽車(chē)電子、利茲大學(xué)和福特VISTEON汽車(chē)系統(tǒng)公司。 經(jīng)過(guò)了四年的研究和準(zhǔn)備,MISRA于1998年發(fā)布了一個(gè)針對(duì)汽車(chē)工業(yè)軟件安全性的C語(yǔ)言編程規(guī)范——《汽車(chē)專用軟件的C語(yǔ)言編程指南》(Guidelines for the Use of the C Language in Vehicle Based Software),共有127條規(guī)則,稱為MISRAC:1998。 C語(yǔ)言并不乏國(guó)際標(biāo)準(zhǔn)。國(guó)際標(biāo)準(zhǔn)化組織(International Organization of Standardization,簡(jiǎn)稱ISO)的“標(biāo)準(zhǔn)C語(yǔ)言”經(jīng)歷了從C90、C96到C99的變動(dòng)。但是,嵌入式程序員很難將ISO標(biāo)準(zhǔn)當(dāng)作編寫(xiě)安全代碼的規(guī)范。一是因?yàn)闃?biāo)準(zhǔn)C語(yǔ)言并不是針對(duì)代碼安全的,也并不是專門(mén)為嵌入式應(yīng)用設(shè)計(jì)的;二是因?yàn)椤皹?biāo)準(zhǔn)C語(yǔ)言”太龐大了,很難操作。MISRAC:1998規(guī)范的產(chǎn)生恰恰彌補(bǔ)了這方面的空白。 隨著很多汽車(chē)廠商開(kāi)始接受MISRAC編程規(guī)范,MISRAC:1998也成為汽車(chē)工業(yè)中最為著名的有關(guān)安全性的C語(yǔ)言規(guī)范。2004年,MISRA出版了該規(guī)范的新版本——MISRAC:2004。在新版本中,還將面向的對(duì)象由汽車(chē)工業(yè)擴(kuò)大到所有的高安全性要求(Critical)系統(tǒng)。在MISRAC:2004中,共有強(qiáng)制規(guī)則121條,推薦規(guī)則20條,并刪除了15條舊規(guī)則。任何符合MISRAC:2004編程規(guī)范的代碼都應(yīng)該嚴(yán)格的遵循121條強(qiáng)制規(guī)則的要求,并應(yīng)該在條件允許的情況下盡可能符合20條推薦規(guī)則。 MISRAC:2004將其141條規(guī)則分為21個(gè)類別,每一條規(guī)則對(duì)應(yīng)一條編程準(zhǔn)則。詳細(xì)情況如表1所列。 表1 MISRAC:2004規(guī)則分類
最初,MISRAC:1998編程規(guī)范的建立是為了增強(qiáng)汽車(chē)工業(yè)軟件的安全性?赡茉斐善(chē)事故的原因有很多,如圖1所示,設(shè)計(jì)和制造時(shí)埋下的隱患約占總數(shù)的15%,其中也包括軟件的設(shè)計(jì)和制造。MISRAC:1998就是為了減小這部分隱患而制定的。 MISRAC編程規(guī)范的推出迎合了很多汽車(chē)廠商的需要,因?yàn)橐坏⿵S商在程序設(shè)計(jì)上出現(xiàn)了問(wèn)題,用來(lái)補(bǔ)救的費(fèi)用將相當(dāng)可觀。1999年7月22日,通用汽車(chē)公司(General Motors)就曾經(jīng)因?yàn)槠滠浖O(shè)計(jì)上的一個(gè)問(wèn)題,被迫召回350萬(wàn)輛已經(jīng)出廠的汽車(chē),損失之大可想而知。 MISRAC規(guī)范不僅在汽車(chē)工業(yè)開(kāi)始普及,也同時(shí)影響到了嵌入式開(kāi)發(fā)的其他方向。嵌入式實(shí)時(shí)操作系統(tǒng)μC/OSII的2.52版本雖然已經(jīng)于2000年通過(guò)了美國(guó)航空管理局(FAA)的安全認(rèn)證,但2003年作者就根據(jù)MISRAC:1998規(guī)范又對(duì)源碼做了相應(yīng)的修改,如將 if ((pevent->OSEventTbl[y] &= ~bitx) == 0) { /*… */ } 的寫(xiě)法,改寫(xiě)成 pevent->OSEventTbl[y] &= ~bitx; if (pevent->OSEventTbl[y] == 0) { /*… */ } 發(fā)布了2.62的新版本,并宣稱其源代碼99%符合MISRAC:1998規(guī)范。 一個(gè)程序能夠符合MISRAC編程規(guī)范,不僅需要程序員按照規(guī)范編程,編譯器也需要對(duì)所編譯的代碼進(jìn)行規(guī)則檢查。現(xiàn)在,很多編譯器開(kāi)發(fā)商都對(duì)MISRAC規(guī)范有了支持,比如IAR的編譯器就提供了對(duì)MISRAC:1998規(guī)范127條規(guī)則的檢查功能。 2 MISRAC對(duì)安全性的理解 MISRAC:2004的專家們大都來(lái)自于軟件工業(yè)或者汽車(chē)工業(yè)的知名公司,規(guī)范的制定不僅僅像過(guò)去一樣局限于汽車(chē)工業(yè)的C語(yǔ)言編程,同時(shí)還涵蓋了其他高安全性系統(tǒng)。 |