文獻(xiàn)標(biāo)識(shí)碼: A
DOI:10.16157/j.issn.0258-7998.2017.05.014
中文引用格式: 王繼剛,方芳,張華強(qiáng). 嵌入式操作系統(tǒng)異常處理框架設(shè)計(jì)與實(shí)現(xiàn)[J].電子技術(shù)應(yīng)用,2017,43(5):60-63,66.
英文引用格式: Wang Jigang,F(xiàn)ang Fang,Zhang Huaqiang. Design and implementation of exception handling framework for embe-
dded operating system[J].Application of Electronic Technique,2017,43(5):60-63,66.
0 引言
隨著后PC時(shí)代的到來(lái),嵌入式系統(tǒng)已廣泛應(yīng)用于航空航天、通信、國(guó)防等可靠性要求較高的關(guān)鍵領(lǐng)域,其復(fù)雜度及功能性日益增強(qiáng)。同時(shí),為了高效使用資源,多應(yīng)用、多任務(wù)并行的軟件設(shè)計(jì)方法被普遍采用,這也不可避免地導(dǎo)致了系統(tǒng)中各類(lèi)錯(cuò)誤和異常增多。當(dāng)異常出現(xiàn)時(shí),如果不能有效處理,很有可能導(dǎo)致應(yīng)用程序終止,系統(tǒng)崩潰,甚至引發(fā)災(zāi)難性事故,這是人們不愿看到的。然而,傳統(tǒng)面向硬件的異常處理方法無(wú)法適應(yīng)當(dāng)前嵌入式軟件的變化,必須引入新的機(jī)制,保證系統(tǒng)可靠穩(wěn)定運(yùn)行。
通過(guò)深入分析嵌入式系統(tǒng)對(duì)異常處理的需求,參考現(xiàn)有異常處理機(jī)制的設(shè)計(jì)思想,本文提出一種結(jié)構(gòu)化的異常處理框架模型,將一些新的功能引入其中,并基于自主研發(fā)的電信級(jí)嵌入式操作系統(tǒng)(Carrier Grade Embedded Linux,CGEL)[1],具體實(shí)現(xiàn)了該異常處理框架。
1 嵌入式系統(tǒng)異常處理需求
傳統(tǒng)的嵌入式系統(tǒng)異常處理通常采用中斷響應(yīng)方式,當(dāng)異常發(fā)生時(shí),系統(tǒng)通過(guò)異常向量表跳轉(zhuǎn)到對(duì)應(yīng)的異常處理函數(shù)中。隨著嵌入式系統(tǒng)及應(yīng)用日益復(fù)雜,異常的種類(lèi)也在不斷增多,出現(xiàn)了許多新的需求。本文通過(guò)分析嵌入式應(yīng)用軟件特征,歸納出以下異常處理新的需求。
(1)異常處理框架。為了滿(mǎn)足日益復(fù)雜的異常處理場(chǎng)景,提供具有基本異常處理流程及應(yīng)用開(kāi)發(fā)接口的框架是必要的。該框架既可使異常從發(fā)生到處理都具備完整的處理流程,同時(shí),也為應(yīng)用開(kāi)發(fā)者提供標(biāo)準(zhǔn)的接口,用于自定義異常處理函數(shù)。開(kāi)發(fā)者自定義的內(nèi)容不會(huì)改變整個(gè)異常處理的流程,但能夠豐富某個(gè)階段的異常處理功能。
(2)狀態(tài)機(jī)。缺少異常處理會(huì)降低系統(tǒng)的可靠性,而有缺陷的異常處理也會(huì)導(dǎo)致嚴(yán)重的系統(tǒng)故障。研究表明[2],有相當(dāng)一部分錯(cuò)誤是由不正確的異常處理造成的。狀態(tài)機(jī)可以有效避免異常處理過(guò)程中出現(xiàn)二次異常的問(wèn)題,通過(guò)定義異常處理過(guò)程中的各個(gè)狀態(tài)及狀態(tài)間的跳轉(zhuǎn)條件,規(guī)定了各狀態(tài)下可能的動(dòng)作,從而識(shí)別異常處理過(guò)程中的二次異常,并予以合理地解決。
(3)嵌套異常處理?,F(xiàn)代嵌入式應(yīng)用往往包含多個(gè)任務(wù),存在各種嵌套關(guān)系。異常處理不僅需要隨著函數(shù)調(diào)用的深入形成嵌套關(guān)系,還要隨著函數(shù)調(diào)用的返回逐層解開(kāi),并回退嵌套的堆棧[3]。當(dāng)異常發(fā)生時(shí),異常處理框架首先對(duì)匹配異常處理函數(shù)進(jìn)行搜索,若異常發(fā)生在第10層的函數(shù)調(diào)用,而異常處理函數(shù)在第5層,異常處理框架則需要將當(dāng)前堆棧從第10層逐層回退到第5層,恢復(fù)第5層的運(yùn)行環(huán)境進(jìn)行異常處理。
(4)自定義鉤子函數(shù)。傳統(tǒng)的異常處理機(jī)制與處理器架構(gòu)緊密相關(guān),需要通過(guò)匯編語(yǔ)言對(duì)寄存器操作,這導(dǎo)致軟件的移植性和健壯性很差?,F(xiàn)代操作系統(tǒng)提供了鉤子掛接機(jī)制,在應(yīng)用程序中通過(guò)鉤子函數(shù)接入自定義的異常處理模塊,當(dāng)異常發(fā)生時(shí),鉤子函數(shù)會(huì)捕捉到內(nèi)核發(fā)出的異常信號(hào),獲得控制權(quán)并予以處理。通過(guò)鉤子函數(shù)能夠避免對(duì)寄存器直接操作,獲取異常信息與處理器無(wú)關(guān),有效增強(qiáng)嵌入式軟件的移植性和健壯性。
(5)異常拋出機(jī)制。傳統(tǒng)的嵌入式軟件異常處理只能響應(yīng)系統(tǒng)級(jí)異常,無(wú)法處理程序邏輯異常。而隨著系統(tǒng)復(fù)雜性的增加,程序邏輯上錯(cuò)誤也會(huì)對(duì)系統(tǒng)造成嚴(yán)重的影響。異常拋出[4]是處理程序邏輯異常的有效機(jī)制,但目前大多數(shù)嵌入式軟件編程語(yǔ)言并沒(méi)有提供這種機(jī)制,比如C、匯編等。所以異常處理框架需提供異常拋出機(jī)制,開(kāi)發(fā)者通過(guò)調(diào)用相關(guān)函數(shù)啟動(dòng)異常拋出功能,對(duì)代碼段進(jìn)行監(jiān)控,捕捉異常信息并處理。
面對(duì)現(xiàn)代嵌入式系統(tǒng)對(duì)異常處理機(jī)制提出的需求,國(guó)內(nèi)外研究者進(jìn)行了深入研究并取得了一系列成果。文獻(xiàn)[5]采用有限狀態(tài)機(jī),通過(guò)對(duì)異常上下文信息進(jìn)行分析,有效提升了異常處理的效率和準(zhǔn)確性。但異常處理策略單一,并沒(méi)有解決異常處理過(guò)程中二次異常和異常擴(kuò)散等問(wèn)題。文獻(xiàn)[6]針對(duì)嵌入式系統(tǒng)提出了一種異常定位方法,對(duì)系統(tǒng)運(yùn)行時(shí)出現(xiàn)的異常進(jìn)行分類(lèi),但并未給出異常處理的策略。文獻(xiàn)[7]提出了一種分層次多策略的異常處理框架,通過(guò)檢查點(diǎn)回滾恢復(fù)實(shí)現(xiàn)多級(jí)異常處理。然而,該框架無(wú)法判別異常處理方法本身的缺陷。
針對(duì)這些新的需求,本文設(shè)計(jì)了一個(gè)基于結(jié)構(gòu)化模型的異常處理框架,可提供多層面的解決方案,涵蓋嵌入式系統(tǒng)異常處理的絕大多數(shù)特性,為系統(tǒng)處理各類(lèi)異常提供有效支持。同時(shí),異常處理框架還具有豐富的鉤子函數(shù)掛載接口,開(kāi)發(fā)者可掛載自定義的異常處理模塊,提高程序運(yùn)行的健壯性。
2 異常處理框架的設(shè)計(jì)實(shí)現(xiàn)
2.1 異常處理框架模型
異常處理框架定義了對(duì)異常的捕獲、處理、保存以及跟蹤等一整套流程。從功能上可分為3個(gè)模塊:異??刂啤惓2东@及異常處理。其中,異??刂剖且粋€(gè)邏輯概念,它負(fù)責(zé)維護(hù)異常處理狀態(tài)機(jī),控制著整個(gè)處理流程,防止異常處理過(guò)程中出現(xiàn)二次異常;異常捕獲則完成系統(tǒng)及應(yīng)用在運(yùn)行時(shí)異常的捕獲,并通過(guò)直接調(diào)用或發(fā)送信號(hào)等手段啟動(dòng)異常處理模塊;異常處理模塊接收異常信息,對(duì)捕獲到的異常提供基本處理方法,也支持用戶(hù)自定義的處理手段。
圖1是異常處理框架在CGEL中的具體實(shí)現(xiàn)模型,框架基于標(biāo)準(zhǔn)的信號(hào)機(jī)制實(shí)現(xiàn)。其中異常捕獲對(duì)系統(tǒng)及應(yīng)用在運(yùn)行過(guò)程中出現(xiàn)的異常進(jìn)行捕獲,通過(guò)信號(hào)調(diào)用異常處理模塊予以處理,整個(gè)處理流程由異??刂颇K維護(hù)。同時(shí),異常處理框架還可以調(diào)用狀態(tài)監(jiān)控等系統(tǒng)服務(wù),進(jìn)行錯(cuò)誤信息的存儲(chǔ)和告警操作,對(duì)異常進(jìn)行有效定位。
為了避免應(yīng)用程序?qū)Φ讓佑布苯硬僮?,異常處理框架為?yīng)用開(kāi)發(fā)提供了線(xiàn)程級(jí)和進(jìn)程級(jí)兩個(gè)層次的回調(diào)鉤子函數(shù)。應(yīng)用中每個(gè)線(xiàn)程都分配一個(gè)異?;卣{(diào)函數(shù)鏈表,當(dāng)出現(xiàn)異常時(shí),框架會(huì)從該線(xiàn)程異?;卣{(diào)鏈表尾部開(kāi)始搜索匹配的異?;卣{(diào)函數(shù),鏈表還可支持程序中多層異常嵌套。而進(jìn)程級(jí)異?;卣{(diào)函數(shù)對(duì)整個(gè)應(yīng)用有效,該函數(shù)只能被掛接一次,當(dāng)所有線(xiàn)程都無(wú)法處理異常時(shí),進(jìn)程級(jí)異?;卣{(diào)函數(shù)將被調(diào)用。開(kāi)發(fā)者可以根據(jù)需要在不同層次的回調(diào)鉤子上掛接自定義的異常處理程序。
2.2 異常處理狀態(tài)機(jī)
通過(guò)對(duì)異常處理所處狀態(tài)的統(tǒng)一管理,狀態(tài)機(jī)能夠幫助異常處理過(guò)程有序地進(jìn)行,支持各種異常處理方法的協(xié)調(diào)運(yùn)行。當(dāng)系統(tǒng)出現(xiàn)異常,狀態(tài)機(jī)會(huì)了解出現(xiàn)異常的狀態(tài),比如是否進(jìn)入了循環(huán)異常、是否為系統(tǒng)異常等,并決定處理異常的動(dòng)作,指導(dǎo)異常處理框架的工作,用最優(yōu)的方式解決異常。為了避免異常重復(fù)進(jìn)入,異常處理模塊的狀態(tài)機(jī)設(shè)計(jì)了3種狀態(tài):正常態(tài)-Normal、異常處理態(tài)-ExcProc、異常升級(jí)處理態(tài)-ExcEscal。各狀態(tài)含義及跳轉(zhuǎn)條件如表1所示。
圖2是異常處理狀態(tài)機(jī)的遷移圖。在CGEL中,應(yīng)用狀態(tài)在線(xiàn)程的線(xiàn)程本地存儲(chǔ)(Thread Local Storage,TLS)中保存,如果使用pthread庫(kù)時(shí),可使用庫(kù)提供的TLS功能,否則需要實(shí)現(xiàn)一個(gè)簡(jiǎn)單的TLS功能來(lái)保存每個(gè)線(xiàn)程的異常處理狀態(tài)。
2.3 多級(jí)異常處理流程
異常控制狀態(tài)機(jī)劃分了異常處理過(guò)程的不同狀態(tài),如何利用其進(jìn)行異常處理,則是異常處理流程的工作。異常處理框架提供了一個(gè)開(kāi)放式的多級(jí)處理流程,開(kāi)發(fā)者可根據(jù)應(yīng)用情況掛接不同級(jí)別的自定義異常處理函數(shù),逐級(jí)完成異常處理功能。異常處理模塊程序流程圖如圖3所示。下面介紹使用框架進(jìn)行多級(jí)異常處理的步驟:
步驟1:在需要使用異常處理功能的應(yīng)用程序中,對(duì)異常處理框架進(jìn)行初始化,掛接主處理函數(shù)Usr_ExcMain();
步驟2:函數(shù)Usr_TrdExcHdlReg()和Usr_TrdExcHdlUnReg()用來(lái)注冊(cè)/注銷(xiāo)線(xiàn)程級(jí)異常處理鉤子,每個(gè)線(xiàn)程維護(hù)一個(gè)異常處理鉤子函數(shù)鏈表,新注冊(cè)的線(xiàn)程級(jí)異常處理鉤子以節(jié)點(diǎn)形式被掛接在鏈表尾;
步驟3:函數(shù)Usr_ProcExcHookReg()和Usr_ProcExc-HookUnReg()用來(lái)注冊(cè)/注銷(xiāo)進(jìn)程級(jí)異常處理鉤子,進(jìn)程級(jí)異常處理鉤子對(duì)整個(gè)應(yīng)用進(jìn)程有效,只能被注冊(cè)一次,后面注冊(cè)的鉤子將覆蓋前面注冊(cè)的;
步驟4:當(dāng)有線(xiàn)程出現(xiàn)異常,框架將調(diào)用Usr_ExcMain()進(jìn)入主處理流程,從尾部節(jié)點(diǎn)開(kāi)始遍歷該線(xiàn)程的異常處理函數(shù)鏈表,通過(guò)節(jié)點(diǎn)上有效異常過(guò)濾函數(shù),判斷節(jié)點(diǎn)能否處理該異常。若能則調(diào)用該節(jié)點(diǎn)上掛接的異常處理鉤子,否則獲取前一節(jié)點(diǎn);
步驟5:如遍歷完線(xiàn)程異常處理鉤子鏈表仍無(wú)法修復(fù),異常處理框架將把該異常升級(jí)為進(jìn)程全局異常,獲取進(jìn)程級(jí)異常處理鉤子函數(shù)gpf_UsrExcHook()予以處理;
步驟6:若所有的異常處理都失敗,將根據(jù)用戶(hù)在函數(shù)Usr_SetExcExitAct()中設(shè)定的動(dòng)作退出該應(yīng)用進(jìn)程。
上述步驟實(shí)現(xiàn)細(xì)節(jié)被封裝在異常處理框架中,用戶(hù)只需調(diào)用框架所提供的注冊(cè)接口掛接自定義的異常處理函數(shù),從而提高了異常處理機(jī)制的可移植性和健壯性。
2.4 異常捕獲
異常捕獲模塊主要完成對(duì)各類(lèi)異常的動(dòng)態(tài)捕捉,對(duì)于捕獲到的硬件異常,異常處理框架通過(guò)傳統(tǒng)的中斷響應(yīng)方式處理。對(duì)于不同的處理器體系,具體的異常編號(hào)和種類(lèi)會(huì)有所不同,但主要有:(1)CPU運(yùn)行異常,如浮點(diǎn)錯(cuò)誤、除零錯(cuò)誤、越權(quán)保護(hù)錯(cuò)誤、非法指令等;(2)內(nèi)存管理異常,如數(shù)據(jù)寫(xiě)異常、頁(yè)面異常、緩沖區(qū)異常等。
除了以上這些硬件異常,應(yīng)用程序還有可能出現(xiàn)邏輯異常。這就需要異常處理框架能夠?qū)Υa段進(jìn)行監(jiān)視,并可啟動(dòng)異常處理流程。拋出異常是一種處理程序邏輯異常的有效機(jī)制,其代碼如下:
TRY_BEGIN
//需要保護(hù)的代碼
THROW 異常
TRY_END
CATCH_BEGIN
//異常處理代碼
CATCH_END
通過(guò)try-catch-throw語(yǔ)句,可以?huà)伋龀绦蛑械漠惓?,轉(zhuǎn)由正常控制流以外的代碼處理。拋出異常對(duì)于分離異常和正常代碼,有效增強(qiáng)異常處理功能非常重要。由于C語(yǔ)言缺乏對(duì)拋出異常的支持,需要在異常處理框架中添加類(lèi)似功能。同時(shí),針對(duì)C語(yǔ)言特征對(duì)拋出異常機(jī)制進(jìn)行了修改,例如:C語(yǔ)言沒(méi)有類(lèi)的概念,框架弱化了異常類(lèi)型的概念,用異常號(hào)(unsigned int)表示異常類(lèi)型;C語(yǔ)言無(wú)關(guān)鍵字try、catch、throw的支持,框架借助宏定義予以實(shí)現(xiàn),如表2所示。
除了設(shè)計(jì)必要的宏外,為了支持在多線(xiàn)程環(huán)境實(shí)現(xiàn)嵌套的try塊,異常處理框架還定義了一種處理try塊的棧式結(jié)構(gòu),該棧式結(jié)構(gòu)在線(xiàn)程初始化階段動(dòng)態(tài)申請(qǐng)空間,其指針保存在TLS中,在線(xiàn)程終止時(shí)釋放。
3 相關(guān)工作
一些主流的嵌入式操作系統(tǒng)也提供了異常處理機(jī)制,下面將分析這些操作系統(tǒng)中異常處理機(jī)制的特點(diǎn),并與本文提出的異常處理框架進(jìn)行對(duì)比。
從異常處理機(jī)制完備性和功能性角度而言,Windows CE[8]是比較全面的,它具有結(jié)構(gòu)化的異常處理機(jī)制,為開(kāi)發(fā)者提供了有力的處理程序錯(cuò)誤或異常的武器。但針對(duì)C語(yǔ)言的異常拋出功能,Windows CE本身不支持,只能結(jié)合編譯器提供語(yǔ)言級(jí)的支持。另外,其異常處理流程沒(méi)有狀態(tài)機(jī)控制,無(wú)法解決在異常處理過(guò)程中出現(xiàn)的錯(cuò)誤。
VxWorks[9]是業(yè)界非常著名的嵌入式實(shí)時(shí)操作系統(tǒng),它提供的全局異常鉤子回調(diào)函數(shù)在嵌入式系統(tǒng)中實(shí)用性很強(qiáng),同時(shí),VxWorks還提供了操作系統(tǒng)缺省異常處理,會(huì)對(duì)異常發(fā)生現(xiàn)場(chǎng)作函數(shù)調(diào)用鏈分析,并將異常信息通過(guò)終端輸出。但是,VxWorks的異常處理機(jī)制非常簡(jiǎn)單,不支持異常處理狀態(tài)機(jī)以及異常拋出等高級(jí)功能,難以滿(mǎn)足現(xiàn)代嵌入式軟件的需求。
由于具有豐富的系統(tǒng)功能、高度定制性及開(kāi)放源碼特征,Linux在嵌入式領(lǐng)域得到了越來(lái)越廣泛的關(guān)注。Linux內(nèi)核[10]沒(méi)有提供統(tǒng)一的異常處理框架,異常處理流程被歸類(lèi)在與CPU體系相關(guān)的代碼中,雖然流程基本一致,但隨著CPU體系不同還是有所差異。應(yīng)用程序需要采用接受異常信號(hào)的方式調(diào)用異常處理流程,不支持鉤子回調(diào)函數(shù),不支持異常處理狀態(tài)機(jī),這些都降低了應(yīng)用程序異常處理的健壯性及可移植性。
本文的異常處理框架結(jié)合了主流嵌入式系統(tǒng)異常處理機(jī)制的特點(diǎn),具有完備的動(dòng)態(tài)鏈表模型和狀態(tài)機(jī),可以有效處理二次異常,還提供適合于嵌入式系統(tǒng)使用的回調(diào)函數(shù),同時(shí)對(duì)程序可能出現(xiàn)的邏輯異常提供了異常拋出機(jī)制,滿(mǎn)足現(xiàn)代嵌入式軟件對(duì)異常處理的需求。表3總結(jié)了上述各異常處理機(jī)制的特點(diǎn),并與CGEL進(jìn)行了功能對(duì)比。
4 結(jié)束語(yǔ)
異常處理已成為提升嵌入式系統(tǒng)健壯性和可用性的關(guān)鍵,本文針對(duì)現(xiàn)代嵌入式應(yīng)用軟件新的異常處理需求,提出了一種結(jié)構(gòu)化的異常處理框架模型,框架包含了3個(gè)主要功能模塊:異常捕獲、異常處理、異??刂疲w嵌入式系統(tǒng)異常處理絕大多數(shù)特性,多級(jí)異常處理流程也為系統(tǒng)處理各類(lèi)異常提供了多層面支持。
目前,異常處理框架已在電信級(jí)嵌入式操作系統(tǒng)CGEL上實(shí)現(xiàn),并成功應(yīng)用于多款電信設(shè)備上,大大增強(qiáng)了系統(tǒng)的可靠性。同時(shí),良好的編程接口縮短了應(yīng)用軟件的開(kāi)發(fā)周期,提高了開(kāi)發(fā)質(zhì)量。高性能和分布式是未來(lái)嵌入式系統(tǒng)的主要特征,動(dòng)態(tài)改變異常處理程序優(yōu)先級(jí)、分布式的異常拋出及處理都是重要的研究方向,有待進(jìn)一步研究。
參考文獻(xiàn)
[1] 王繼剛,鄭緯民,鐘衛(wèi)東,等.基于Linux的混合實(shí)時(shí)操作系統(tǒng)[J].清華大學(xué)學(xué)報(bào),2009,49(7):1012-1015.
[2] Herbert Hecht.A systems engineering approach to exception handling[C].Proceeding of the Third International Conference on Systems.Washington DC,USA,2008:190-195.
[3] 朱劍鋒,繆萬(wàn)勝,康介祥.基于堆棧回溯的異常處理[J].計(jì)算機(jī)工程與設(shè)計(jì),2014,35(12):4176-4180.
[4] Mao Chengying,Lu Yansheng.Study on the analysis and testing of exception handling in C++ programs[J].Mini-Micro Systems,2006,27(3):481-485.
[5] Cabdq Filho,Rmc Andrade,Ls Rocha,et al.ConExT-U:A context-aware exception handling mechanism for task-based ubiquitous systems[C].28th International Conference on Advanced Information Networking and Applications Work-shops.BC,Canada,2014:127-132.
[6] SAWADPONG P,ALLEN E B,WILLIAMS B J.Exception handling defects:an empirical study[C].14th International Symposium on High-Assurance Systems Engineering.Washington DC,USA,2012:90-97.
[7] Lu Zhou,Zhang Kailong,Zhou Xingshe.A software Fault-Tol-erant method based on exception handing in RT/E system[C].10th IEEE International Conference on Trust,Security and Privacy in Computing and Communications,Changsha,China,2011:1283-1287.
[8] 羊建林,周安民.Windows異常處理與軟件安全[J].信息安全與通信保密,2011,9(4):58-60.
[9] Wind River.VxWorks kernel programmers guide 6.9[M].California:Wind River Systems,2011.
[10] Robert Love.Linux kernel development[M].USA:Addison-Wesley Professional,2010.
作者信息:
王繼剛1,方 芳2,張華強(qiáng)1
(1.中興通訊股份有限公司 技術(shù)規(guī)劃部,江蘇 南京210012;
2.信息產(chǎn)業(yè)電子第十一設(shè)計(jì)研究院科技工程股份有限公司 信息中心,四川 成都610021)