概述
嵌入式系統已經具有相當長的歷史,最初是在軍事、航空航天、工業過程控制等領域。從20世紀90年代中後期開始,網際網路、通信、信息家電等的興起使嵌入式系統滲透到了人們的日常生活當中,這也使得計算機產業從PC時代來到了以普及計算(Pervasive Computing)和嵌入式系統為重要代表的後PC時代。嵌入式系統是以套用為中心的計算機系統,一般具有實時性、專用性和資源有限性等特點,因此嵌入式軟體的設計既具備一般計算機系統的軟體設計共性,也具有其特殊性。
結構化設計方法
結構化設計方法是目前嵌入式軟體最成熟、使用最廣泛的設計方法,它又分成兩大類:單任務的結構化設計方法和多任務的結構化設計方法。
單任務的結構化設計方法
嵌入式軟體在邏輯上可以抽象成一個不斷處理外部事件的過程,單任務的結構化設計方法的主要思想就是按照結構化的設計原則分別設計好各個事件的處理模組,然後在一個主循環中依次循環調用這些模組(如下面的程式段所示)。這種設計方法具有軟體結構簡單、運行效率高、占用資源少和可以不需要OS支持等優點,但是它也有以下的缺點:
事件處理之間無優先權並且不可搶占,當一個緊迫事件來臨時,如果處理該事件的模組剛被調用,則必須要等到下一次循環才能被調用處理;
事件處理模組之間的互斥和同步原語操作需要用戶自己來編程實現。單任務的結構化設計方法比較適合於很簡單的嵌入式系統,這些系統的硬體資源非常緊張,並且處理的事件比較單一,如簡單的單片機控制系統;另外在一些處理的事件比較單一併且要求高速的場合也可以使用,例如數位訊號處理(DSP)。
單任務的結構化嵌入式軟體體系框架如下:
While(繼續運行)
調用事件處理模組1;
調用事件處理模組2;
多任務的結構化設計方法
多任務的結構化設計方法的基本思想仍然是先劃分模組,然後進行模組綜合,與單任務的結構化設計方法不同之處在於這些並發模組並不是被綜合在一個主循環中,而是被綜合分配到多個任務中,在多任務運行時環境(RTOS)協調下執行。系統地描述了一種多任務的結構化設計方法DARTS———一種結構化分析和設計方法在嵌入式軟體設計中的擴展。DARTS在結構化分析和設計過程中,需要進行任務的劃分,通過對事件處理模組的相互關係進行分析,按照它們之間的時間特性、緊急程度、是否可以並行操作、相互之間的耦合強度等特性,將模組分配到相應的任務中去。另外,DARTS利用任務通信模組和任務同步模組來完成任務間的通信、互斥與同步。DARTS方法是多任務的結構化設計方法的典型代表,在目前的嵌入式軟體中被廣泛使用。與單任務的結構化設計方法比較起來,任務之間可以按照優先權進行搶占,在設計時把緊急事件的處理模組分配到高優先權的任務中,這樣緊急事件就可以隨時得到優先處理;另外事件處理模組之間的通信、互斥和同步通過任務通信模組和任務同步模組來完成,這些通信模組和同步模組抽象了所有嵌入式軟體的共同特點,在所有嵌入式軟體中都可以使用,並且它們在實時作業系統(RTOS)提供的通信原語、同步互斥原語基礎上來實現,這樣減輕了應用程式開發人員的負擔,使套用開發人員專注於與套用本身相關的設計。當然,多任務的結構化設計方法對系統硬體資源的要求比單任務的結構化設計方法高一些,並且需要RTOS的支持,因此在一些硬體資源很緊張的嵌入式系統中無法使用。
面向對象的設計方法
結構化的軟體設計方法雖然獲得了很大的成功,但是設計出來的軟體在擴展性、維護性等方面卻不能盡如人意,主要原因在於結構化的設計方法將數據和在數據上的操作分離開來,封裝性和信息隱藏性不好。面向對象(OO)設計方法將數據與數據上的操作封裝在對象這個實體中,對象外界不能直接對對象內部進行訪問和操作,只能通過訊息的方式間接訪問對象。OO方法符合人們的思考方式,並使問題空間和解空間的描述相一致,各個對象之間不需要了解對方內部細節,並且提供了繼承、多態、重載等方式來提高軟體的重用性;另外,在OO設計方法中可以採用面向對象的應用程式框架的方式來捕捉大規模套用的設計模式,提高了軟體體系結構的重用性。因此,OO設計方法能夠使軟體開發人員理解和管理更大更複雜的軟體,提高軟體的擴展性、維護性和重用性。
面向對象的嵌入式軟體設計方法包括面向對象的系統建模、面向對象的系統設計、對象的詳細設計這幾個典型步驟。文獻提出了一種面向對象的實時多任務設計方法,它在面向對象的系統建模階段,使用UML進行對象建模,使用MSC進行用戶實例建模,從而分別描述了系統的靜態和動態行為;在面向對象的系統設計階段,根據系統建模結果進行套用的體系結構設計,主要過程包括體系結構描述(根據對象模型中的並行類及其它因素確定體系結構中的高級對象),細化高級對象,描述對象之間的通信關係,確定被動對象等,並使用SDL來描述相關的設計;在對象的詳細設計階段,包括並行對象和被動對象的詳細設計,前者使用SDL的進程圖來描述,後者使用UML的類圖來描述。文獻的方法不但具有面向對象的設計方法的好處,還充分利用了各種形式化的語言和各種輔助工具,提高了嵌入式軟體的開發效率。
從以上敘述可知,為了將面向對象設計方法套用到嵌入式軟體設計中,在對象中明確引入了並行特性,從而有了並行對象和被動對象的概念。另一種面向對象的嵌入式軟體設計—自適應通信環境ACE(Adaptive Communication Environment)框架,使用主動對象(Active Object)或反應式對象(Reactive Object)來為對象引入並行特性。同樣,將面向對象設計方法套用到嵌入式軟體設計中的另一種方式是在對象的方法中引入實時特性,建立實時對象的概念,TMO和PBO就是兩個典型的代表。TMO將對象中的方法分成以時間驅動和以訊息驅動兩類,在設計時,對具有定時特性的操作就用時間驅動類方法來描述。TMO利用BBC(Basic Concurrent Constraint)規則控制對象方法之間的調度,BBC規則中基本的一條就是時間驅動類方法的優先權高於訊息驅動類方法;PBO採用自治計算模型,PBO中的每個方法在運行時就假定需要的輸入已經準備好,每個方法被調度執行時都是一次執行完畢,不會被其它方法打斷,而PBO之間的互斥與同步(包括同一PBO對象中的方法驅動)交由系統處理,使PBO方法之間以及PBO對象之間的同步簡化。
面向對象的嵌入式軟體設計方法能夠充分利用面向對象的優點,並且能夠利用許多的形式化語言和輔助工具來協助軟體開發,使嵌入式軟體的開發效率、擴展性、維護性和重用性都有很大的提高。嵌入式軟體的面向對象設計與普通軟體的面向對象設計並沒有本質的不同,主要差異是在對象中引入了嵌入式軟體的特徵(並行性、實時性、可靠性等)。很明顯,面向對象的嵌入式軟體設計方法一般需要面向對象的程式語言(例如C++)的支持。但是,面向對象的程式語言占用記憶體空間比面向過程的程式語言要多,運行效率也比不上後者。在現有的RTOS上實現面向對象的嵌入式軟體設計,一般採用如圖所示的模型。RTOS的對象化封裝層將RTOS的API封裝成對象的類(如C++類),面向對象的運行支撐層在對象化封裝層基礎上,將套用中共性的東西抽象出來形成對象的類和面向對象的應用程式框架(例如上文中的ACE框架及其包含的主動對象、反應式對象等)並為對象框架的運行提供支撐,套用層則在面向對象的運行支撐層提供的框架和類以及RTOS對象化封裝層提供的類的基礎上進行構建。引入的面向對象的運行支撐層和RTOS對象化封裝層進一步加大了記憶體空間的占用,降低了運行效率;另外面向對象的運行支撐層如何抽象出套用中共性的對象和框架非常關鍵,甚至影響到面向對象的嵌入式軟體設計方法的成敗,而這個問題目前還是一個開放的問題,上文中的ACE、TMO、PBO等都只是在某一類套用中使用效果比較好。但是不管如何,面向對象的嵌入式軟體設計方法是設計大型複雜嵌入式軟體的有效途徑。
基於構件的設計方法
近年來,軟體生產線的概念被人們提了出來,其最終目的就是希望軟體象硬體一樣進行生產。構件化的軟體開發主要通過提高軟體的重用性來提高軟體開發效率,同時它強調軟體體系結構的重要性,認為應該在軟體體系結構層次上對軟體進行設計和維護,即所謂“粗粒度”軟體設計。構件的定義很多,比較典型的有:構件在邏輯上可以看著被多個軟體系統所復用的具有獨立功能的系統構成成分;構件是系統的基本構造單元,具有較好的自包含性;構件可以視為一個通過接口對外界提供服務或向外界請求服務的黑盒,多個構件可以組成一個更高層次的構件,構件比對象提供了更高的設計抽象。從以上的定義可以看出構件最重要的特點是其獨立性、重用性和具有層次的抽象性,重用性強調構件的目的是為了軟體的重用性,獨立性則強調構件達到該目的手段,即通過其功能和實現的獨立性從而使它能夠在很多的環境中被使用,具有層次的抽象性表明構件的廣泛適用性,從整個軟體系統到具體的每個細小的功能塊都可以使用構件概念來描述和設計。構件化軟體設計的研究內容可以分成領域工程和套用工程兩部分。領域工程的主要任務是獲取構件,存在大量可復用的構件是有效地使用構件進行套用軟體設計的前提,而領域工程是獲取構件、構架的主要途徑。領域是一組具有相似或相近軟體需求的套用系統所覆蓋的功能區域,領域工程是為一組相似或相近系統的套用工程建立基本能力和必備基礎的過程。領域工程過程劃分為領域分析、領域設計、領域實現等多個活動,其中的活動與結果如圖所示。套用工程的主要任務是構件復用,利用領域工程結果進行軟體系統的開發,與普通的軟體開發過程類似,套用工程也可以劃分為分析(需求獲取)、設計、實現等階段。不同的是,本過程中的每一階段皆可以從構件庫中獲得可復用的領域工程結果,並將其作為本階段集成與開發的基礎,套用工程中的活動與結果見圖。
領域工程研究的核心是構件模型和軟體體系結構(軟體構架)這兩個相互關聯的問題,不同的構件只能在相應的軟體構架中使用,就象計算機硬體上不同匯流排的擴展卡只能插在相應的擴展匯流排上,因此基於構件的套用軟體設計也可以認為是基於體系結構(構架)的軟體設計,也有人稱之為基於“構件———構架”的套用軟體設計。目前針對構件和構架的研究包括:提出各種“構件———構架”模型、提出各種形式化的描述方法和可重用構件的產生等。在構件和構架模型中,把構件與連線件相區別是一個非常重要的思想,這種思想把構件的功能與構件間的互動分離,這種分離提高了構件的獨立性和重用性,因為構件在生產時不需要考慮其使用環境(與其它構件的互動)。同時在大型分散式複雜軟體中引入了具有更高抽象層次的Agent概念,利用Agent來實現軟體的高抽象層次的構件和連線件,能夠在不同層次上清晰描述和實現構件化的軟體體系結構———在此把這些構件/構架模型稱為高級構件/構架模型,而且也有了一些針對基礎構件和構架模型的業界標準提供給用戶直接使用。構件庫管理為套用工程重用已有的構件提供支持,隨著構件化的軟體設計逐漸成為主流,能夠重用的構件必然越來越多,用戶花在查找適合自己需要的構件上的成本也必然在整個軟體開發過程中占據越來越大的比例,所以構件庫的管理也開始受到研究者的注意。系統分析了構件重用成本問題,並給出了量化的公式,在該公式中,涉及到構件庫的大小和組織問題,給出了構件庫管理的兩個性能指標:查全率和查準率。所謂查全率是指具備用戶指定特徵的構件都能夠反饋給用戶挑選;所謂查準率率是指儘量反饋精確具備用戶指定特徵的構件,不相關的構件不要反饋給用戶,以減小用戶篩選適合自己需要的構件的工作量。
可重用構件和構架的獲取也是學術界和工業界關注的問題之一,因為只有構件庫中有豐富的構件才能提供給用戶使用。如何充實構件庫(可重用構件和構架的獲取)成了實踐者的一個緊迫問題。獲取可重用構件有兩種途徑:第一種方法就是按照構件———構架模型來從頭生產可重用的構件和構架,為以後的套用開發服務;第二種方法就是從傳統的軟體中提取出可重用的構件和構架。很顯然,第二種方法更具有吸引力,因為它儘可能減小了重複開發。從傳統的軟體中提取出可重用的構件和構架可以看成軟體反向工程的一部分。套用工程解決的核心問題是如何利用領域工程的構件和構架,進行應用程式的生成,這個過程也稱之為基於構件的軟體開發過程,它可以分成三步:構件的抽取、構件的組合、構件的適應性修改。構件的組合就是指把各個構件(包括連線件)組裝起來形成套用系統的過程,該過程也可以稱為基於構件的軟體設計過程。基於構件的套用軟體設計是一個自底向上和自頂向下相結合的設計過程。這個過程的關鍵是如何把一個套用系統的需求進行分解,使其儘量能夠通過用已存在的構件組合來完成,構架模型(軟體體系結構)為這個分解過程提供了指導方向。對分解過程採用的方法進行了比較全面的敘述,描述了通過枚舉選擇的構件組合的自底向上的設計算法及其改進算法。構件的適應性修改也是相當重要的,因為許多年來,我們已經積累了大量的軟體製品,可以把它們進行適應性修改使之構件化加入到構件庫中,從而適合在構件化軟體設計中使用。目前有關這方面的研究不是非常系統,也沒有提出一個普遍化的方法來進行這項工作。
嵌入式軟體因其套用環境的約束,基於構件的軟體設計方法在嵌入式軟體開發中還會遇到特有的技術問題,綜合論述了基於構件的嵌入式軟體設計中面臨的問題:降低構件間在時間和空間上的耦合性;端到端的可靠性依賴;資源的有限性(時間和空間資源);對平台的依賴性。該文還提出基於構件的嵌入式軟體設計中最重要的是定義一種構件/構架模型,該模型要把資源和系統的非功能性需求方面一起考慮。總的說來,嵌入式軟體的構件化開發技術遇到的特殊技術問題主要有:(1)在模型和模型描述中引入實時特性;(2)抽象出一個可以靈活定製並滿足實時約束的通用體系結構;(3)軟體的形式化技術,嵌入式實時軟體往往要求高可靠性,而軟體的形式化技術可以保證生成正確的軟體;(4)軟體的動態演化技術,嵌入式實時系統往往需要長期不間斷的運行,在運行過程中軟體不可避免地要進行升級,如何進行軟體動態升級也是嵌入式軟體研究的一個重點。構件化的嵌入式軟體設計由於使軟體模組化,各模組間的獨立性強,為軟體動態升級提供了很好的基礎。但是為了達到構件的動態配置與替換,仍然有相當多的問題要解決;(5)在語言級上支持基於構件的實時系統的編程;(6)從實時應用程式中抽取可重用的構件的問題等。
目前在嵌入式軟體中使用基於構件的設計方法研究較多的是基於實時CORBA的研究,但是這些研究遠未成熟。基於構件的軟體設計建立在面向對象設計基礎之上,它把對象對外的接口聲明與對象內部的接口實現相分離,一個構件在修改自己的接口時,只影響與修改接口相互動的構件,與被修改構件的其它接口相互動的構件不受任何影響。因此,構件化的軟體具有面向對象的軟體的所有優點,並且重用和擴展性更高,可以做到在二進制級別上的重用。相對而言,基於構件的嵌入式軟體設計方法對嵌入式系統的硬體資源要求更多,目前較多套用在大型分散式嵌入式軟體系統中,要使這種方法在嵌入式軟體設計中普及開來,需要等待嵌入式系統硬體的發展和基於構件軟體設計方法的相關問題的解決。