嵌入式軟件架構設計_第1頁
嵌入式軟件架構設計_第2頁
嵌入式軟件架構設計_第3頁
嵌入式軟件架構設計_第4頁
嵌入式軟件架構設計_第5頁
已閱讀5頁,還剩41頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、嵌入式系統(tǒng)軟件架構設計目錄1.前言42.決定架構的因素和架構的影響42.1.常見的誤解52.1.1.小型的系統(tǒng)不需要架構52.1.2.敏捷開發(fā)不需要架構73.嵌入式環(huán)境下軟件設計的特點73.1.和硬件密切相關73.2.穩(wěn)定性要求高83.3.內(nèi)存不足83.3.1.虛擬內(nèi)存技術83.3.2.兩段式構造93.3.3.內(nèi)存分配器103.3.4.內(nèi)存泄漏113.4.處理器能力有限,性能要求高113.4.1.抵御新技術的誘惑113.4.2.不要有太多的層次113.5.存儲設備易損壞,速度較慢123.5.1.損耗均衡123.5.2.錯誤恢復123.6.故障成本高昂134.軟件框架144.1.嵌入式軟件架構面

2、臨的問題144.2.什么是框架144.2.1.軟件復用的層次144.2.2.針對高度特定領域的抽象154.2.3.解除耦合和應對變化164.2.4.框架可以實現(xiàn)和規(guī)定非功能性需求164.3.一個框架設計的實例174.3.1.基本架構174.3.2.功能特點174.3.3.分析184.3.4.實際效果234.4.框架設計中的常用模式234.4.1.模板方法模式234.4.2.創(chuàng)建型模式234.4.3.消息訂閱模式244.4.4.裝飾器模式244.5.框架的缺點255.自動代碼生成265.1.機器能做的事就不要讓人來做265.2.舉例265.2.1.消息的編碼和解碼26代碼275.2.3.小結28

3、5.2.4.Google Protocol Buffer286.面向語言編程(LOP)306.1.從自動化代碼生成更進一步306.2.優(yōu)勢和劣勢326.3.在嵌入式系統(tǒng)中的應用327.測試337.1.可測試性是軟件質(zhì)量的一個度量指標337.2.測試驅(qū)動的軟件架構347.3.系統(tǒng)測試347.3.1.界面自動化測試347.3.2.基于消息的自動化測試367.3.3.自動化測試框架367.3.4.回歸測試387.4.集成測試387.5.單元測試387.5.1.圈復雜度測量417.5.2.扇入扇出測量427.5.3.框架對單元測試的意義428.維護架構的一致性429.一個實際嵌入式系統(tǒng)架構的演化439

4、.1.數(shù)據(jù)處理449.2.窗口管理44模式459.4.大量類似模塊,低效的復用469.5.遠程控制469.6.自動化的TL1解釋器479.7.測試的難題479.8.小結4710.總結481. 前言嵌入式是軟件設計領域的一個分支,它自身的諸多特點決定了系統(tǒng)架構師的選擇,同時它的一些問題又具有相當?shù)耐ㄓ眯裕梢酝茝V到其他的領域。本課程試圖從嵌入式軟件架構設計出發(fā),啟發(fā)大家對軟件架構設計的理解。本課程的很多內(nèi)容是對謝老師課程在嵌入式領域的具體闡述。提起嵌入式軟件設計,傳統(tǒng)的印象是單片機,匯編,高度依賴硬件。傳統(tǒng)的嵌入式軟件開發(fā)者往往只關注實現(xiàn)功能本身,而忽視諸如代碼復用,數(shù)據(jù)和界面分離,可測試性等因

5、素。從而導致嵌入式軟件的質(zhì)量高度依賴開發(fā)者的水平,成敗系之一身。隨著嵌入式軟硬件的飛速發(fā)展,今天的嵌入式系統(tǒng)在功能,規(guī)模和復雜度各方面都有了極大的提升。比如,Marvell公司的PXA3xx系列的最高主頻已經(jīng)達到800Mhz,內(nèi)建USB,WIFI,2D圖形加速,32位DDR內(nèi)存。在硬件上,今天的嵌入式系統(tǒng)已經(jīng)達到甚至超過了數(shù)年前的PC平臺。在軟件方面,完善的操作系統(tǒng)已經(jīng)成熟,比如Symbian, Linux, WinCE。基于完善的操作系統(tǒng),諸如字處理,圖像,視頻,音頻,游戲,網(wǎng)頁瀏覽等各種應用程序?qū)映霾桓F,其功能性和復雜度比諸PC軟件不遑多讓。原來多選用專用硬件和專用系統(tǒng)的一些商業(yè)設備公司也

6、開始轉(zhuǎn)換思路,以出色而廉價的硬件和完善的操作系統(tǒng)為基礎,用軟件的方式代替以前使用專有硬件實現(xiàn)的功能,從而實現(xiàn)更低的成本和更高的可變更,可維護性。2. 決定架構的因素和架構的影響架構不是一個孤立的技術的產(chǎn)物,它受多方面因素的影響。同時,一個架構又對軟件開發(fā)的諸多方面造成影響。軟件架構軟件規(guī)模生命周期非功能性需求非功能性需求團隊組成開發(fā)模式下面舉一個具體的例子。摩托車的發(fā)動機在出廠前必須通過一系列的測試。在流水線上,發(fā)動機被送到每個工位上,由工人進行諸如轉(zhuǎn)速,噪音,振動等方面的測試。要求實現(xiàn)一個嵌入式設備,具備以下基本功能:1. 安裝在工位上,工人上班前開啟并登錄。2. 通過傳感器自動采集測試數(shù)據(jù)

7、,并顯示在屏幕上。3. 記錄所有的測試結果,并提供統(tǒng)計功能。比如次品率。如果你是這個設備的架構師,哪些問題是在設計架構的時候應該關注的呢?2.1. 常見的誤解2.1.1. 小型的系統(tǒng)不需要架構有相當多的嵌入式系統(tǒng)規(guī)模都較小,一般是為了某些特定的目的而設計的。受工程師認識,客戶規(guī)模和項目進度的影響,經(jīng)常不做任何架構設計,直接以實現(xiàn)功能為目標進行編碼。這種行為表面上看滿足了進度,成本,功能各方面的需求,但是從長遠來看,在擴展和維護上付出的成本,要遠遠高于最初節(jié)約的成本。如果系統(tǒng)的最初開發(fā)者繼續(xù)留在組織內(nèi)并負責這個項目,那么可能一切都會正常,一旦他離開,后續(xù)者因為對系統(tǒng)細節(jié)的理解不足,就可能引入更多

8、的錯誤。要注意,嵌入式系統(tǒng)的變更成本要遠遠高于一般的軟件系統(tǒng)。好的軟件架構,可以從宏觀和微觀的不同層次上描述系統(tǒng),并將各個部分隔離,從而使新特性的添加和后續(xù)維護變得相對簡單。舉一個城鐵刷卡機的例子,這個例子在前面的課程中出現(xiàn)過。簡單的城鐵刷卡機只需要實現(xiàn)如下功能:一個While循環(huán)足以實現(xiàn)這個系統(tǒng),直接就可以開始編碼調(diào)試。但是從一個架構師的角度,這里有沒有值得抽象和剝離的部分呢?1. 計費系統(tǒng)。計費系統(tǒng)是必須抽象的,比如從單次計費到按里程計費。2. 傳感器系統(tǒng)。傳感器包括磁卡感應器,投幣器等。設備可能更換。3. 故障處理和恢復??紤]到較高的可靠性和較短的故障恢復時間,這部分有必要單獨設計。未來

9、很可能出現(xiàn)的需求變更:1. 操作界面。是否需要抽象出專門的Model來?以備將來實現(xiàn)View。2. 數(shù)據(jù)統(tǒng)計。是否需要引入關系型數(shù)據(jù)庫?如果直接以上面的流程圖編碼,當出現(xiàn)變更后,有多少代碼可以復用?不過,也不要因此產(chǎn)生過度的設計。架構應當立足滿足當前需求,并適當?shù)目紤]重用和變更。2.1.2. 敏捷開發(fā)不需要架構極限編程,敏捷開發(fā)的出現(xiàn)使一些人誤以為軟件開發(fā)無需再做架構了。這是一個很大的誤解。敏捷開發(fā)是在傳統(tǒng)瀑布式開發(fā)流程出現(xiàn)明顯弊端后提出的解決方案,所以它必然有一個更高的起點和對開發(fā)更嚴格的要求。而不是倒退到石器時代。事實上,架構是敏捷開發(fā)的一部分,只不過在形式上,敏捷開發(fā)推薦使用更高效,簡單

10、的方式來做設計。比如畫在白板上然后用數(shù)碼相機拍下的UML圖;用用戶故事代替用戶用例等。測試驅(qū)動的敏捷開發(fā)更是強迫工程師在寫實際代碼前設計好組件的功能和接口,而不是直接開始寫代碼。敏捷開發(fā)的一些特征:1. 針對比傳統(tǒng)開發(fā)流程更大的系統(tǒng)2. 承認變化,迭代架構3. 簡潔而不混亂4. 強調(diào)測試和重構3. 嵌入式環(huán)境下軟件設計的特點要談嵌入式的軟件架構,首先必須了解嵌入式軟件設計的特點。3.1. 和硬件密切相關嵌入式軟件普遍對硬件有著相當?shù)囊蕾囆?。這體現(xiàn)在幾個方面:1. 一些功能只能通過硬件實現(xiàn),軟件操作硬件,驅(qū)動硬件。2. 硬件的差異/變更會對軟件產(chǎn)生重大影響。3. 沒有硬件或者硬件不完善時,軟件無

11、法運行或無法完整運行。這些特點導致幾方面的后果:1. 軟件工程師對硬件的理解和熟練程度會很大程度的決定軟件的性能/穩(wěn)定性等非功能性指標,而這部分一向是相對復雜的,需要資深的工程師才能保證質(zhì)量。2. 軟件對硬件設計高度依賴,不能保持相對穩(wěn)定,可維護性和可重用性差3. 軟件不能離開硬件單獨測試和驗證,往往需要和硬件驗證同步進行,造成進度前松后緊,錯誤定位范圍擴大。針對這些問題,有幾方面的解決思路:1. 用軟件實現(xiàn)硬件功能。選用更強大的處理器,用軟件來實現(xiàn)部分硬件功能,不僅可以降低對硬件的依賴,在響應變化,避免對特定型號和廠商的依賴方面都很有好處。這在一些行業(yè)里已經(jīng)成為了趨勢。在PC平臺也經(jīng)歷了這樣

12、的過程,比如早期的漢卡。2. 將對硬件的依賴獨立成硬件抽象層,盡可能使軟件的其他部分硬件無關,并可以脫離硬件運行。一方面將硬件變更甚至換件的風險控制在有限的范圍內(nèi),另一方面提高軟件部分的可測試性。3.2. 穩(wěn)定性要求高大部分嵌入式軟件都對程序的長期穩(wěn)定運行有較高的要求。比如手機經(jīng)常幾個月開機,通訊設備則要求24*7正常運行,即使是通訊上的測試設備也要求至少正常運行8小時。為了穩(wěn)定性的目標,有一些比較常用的設計手段:1. 將不同的任務分布在獨立的進程中。良好的模塊化設計是關鍵2. Watch Dog, Heart beat,重新啟動失效的進程。3. 完善而統(tǒng)一的日志系統(tǒng)以快速定位問題。嵌入式設備

13、一般缺乏有力的調(diào)試器,日志系統(tǒng)尤其重要。4. 將錯誤孤立在最小的范圍內(nèi),避免錯誤的擴散和連鎖反應。核心代碼要經(jīng)過充分的驗證,對非核心代碼,可以在監(jiān)控或者沙盒中運行,避免其破壞整個系統(tǒng)。舉例,Symbian上的GPRS訪問受不同硬件和操作系統(tǒng)版本影響,功能不是非常穩(wěn)定。其中有一個版本上當關閉GPRS連接時一定會崩潰,而且屬于known issue。將GPRS連接,HTTP協(xié)議處理,文件下載等操作獨立到一個進程中,雖然每次操作完畢該進程都會崩潰,對用戶卻沒有影響。5. 雙備份這樣的手段較少采用3.3. 內(nèi)存不足雖然當今的嵌入式系統(tǒng)的內(nèi)存比之以K計數(shù)的時代已經(jīng)有了很大的提高,但是隨著軟件規(guī)模的增長,

14、內(nèi)存不足的問題依然時時困擾著系統(tǒng)架構師。有一些原則,架構師在進行設計決策的時候可以參考:3.3.1. 虛擬內(nèi)存技術有一些嵌入式設備需要處理巨大的數(shù)據(jù)量,而這些數(shù)據(jù)不可能全部裝入內(nèi)存中。一些嵌入式操作系統(tǒng)不提供虛擬內(nèi)存技術,比如WinCE4.2每個程序最多只能使用32M內(nèi)存。對這樣的應用,架構師應該特別設計自己的虛擬內(nèi)存技術。所謂的虛擬內(nèi)存技術的核心是,將暫時不太可能使用的數(shù)據(jù)移出內(nèi)存。這涉及到一些技術點:1. 引用計數(shù),正在使用的數(shù)據(jù)不能移出。2. 使用預測,預測下一個階段某個數(shù)據(jù)的使用可能性。基于預測移出數(shù)據(jù)或者提前裝入數(shù)據(jù)。3. 占位數(shù)據(jù)/對象。4. 高速緩存。在復雜數(shù)據(jù)結果下緩存高頻率使

15、用的數(shù)據(jù),直接訪問。5. 快速的持久化和裝載。下圖是一個全國電信機房管理系統(tǒng)的界面示意圖:每個節(jié)點下都有大量的數(shù)據(jù)需要裝載,可以使用上述技術將內(nèi)存占用降到最低。3.3.2. 兩段式構造在內(nèi)存有限的系統(tǒng)里,對象構造失敗是必須要處理的問題,失敗的原因中最常見的則是內(nèi)存不足(實際上這也是對PC平臺的要求,但是在實際中往往忽略,因為內(nèi)存實在便宜)。兩段式構造就是一種常用而有效的設計。舉例來說:CMySimpleClass:class CMySimpleClass      public:     CMySimpleClas

16、s();     CMySimpleClass();     .   private:     int SomeData;CMyCompoundClass:class CMyCompoundClass             public:        CMyCompoundClass();  

17、     CMyCompoundClass();       .      private:        CMySimpleClass* iSimpleClass; ;在CMyCompoundClass的構造函數(shù)里初始化iSimpleClass對象。CMyCompoundClass:CMyCompoundClass()       iSimpleClass

18、 = new CMySimpleClass;  當創(chuàng)建CMyCompoundClass的時候會發(fā)生什么呢?CMyCompoundClass* myCompoundClass = new CMyCompoundClass;1. 為CMyCompoundClass的對象分配內(nèi)存2.  調(diào)用CMyCompoundClass對象的構造函數(shù)3. 在構造函數(shù)中創(chuàng)建一個CMySimpleClass的實例4. 構造函數(shù)結束返回一切看起來都很簡單,但是如果第三步創(chuàng)建CMySimpleClass對象的時候發(fā)生內(nèi)存不足的錯誤怎么辦呢?構造函數(shù)無法返回任何錯誤信息以提示調(diào)用者構造沒有成功。調(diào)用者于

19、是獲得了一個指向CMyCompoundClass的指針,但是這個對象并沒有構造完整。如果在構造函數(shù)中拋出異常會怎么樣呢?這是個著名的噩夢,因為析構函數(shù)不會被調(diào)用,在創(chuàng)建CMySimpleClass對象之前如果分配了資源就會泄露。關于在構造函數(shù)中拋出異常可以單講一個小時,但是有一個建議是:盡量避免在構造函數(shù)中拋出異常。所以,使用兩段式構造法是一個更好的選擇。簡單的說,就是在構造函數(shù)避免任何可能產(chǎn)生錯誤的動作,比如分配內(nèi)存,而把這些動作放在構造完成之后,調(diào)用另一個函數(shù)。比如:AddressBook* book = new AddressBook()If(!book->Construct()d

20、elete book;book = NULL;這樣可以保證當Construct不成功的時候釋放已經(jīng)分配的資源。在最重要的手機操作系統(tǒng)Symbian上,二段式構造法普遍使用。3.3.3. 內(nèi)存分配器不同的系統(tǒng)有著不同的內(nèi)存分配的特點。有些要求分配很多小內(nèi)存,有的則需要經(jīng)常增長已經(jīng)分配的內(nèi)存。一個好的內(nèi)存分配器對嵌入式的軟件的性能有時具有重大的意義。應該在系統(tǒng)設計時保證整個系統(tǒng)使用統(tǒng)一的內(nèi)存分配器,并且可以隨時更換。3.3.4. 內(nèi)存泄漏內(nèi)存泄漏對嵌入式系統(tǒng)有限的內(nèi)存是非常嚴重的。通過使用自己的內(nèi)存分配器,可以很容易的跟蹤內(nèi)存的分配釋放情況,從而檢測出內(nèi)存泄漏的情況。3.4. 處理器能力有限,性能

21、要求高這里不討論實時系統(tǒng),那是一塊很大的專業(yè)話題。對一般的嵌入式系統(tǒng)而言,由于處理器能力有限,要特別注意性能的問題。一些很好的架構設計由于不能滿足性能要求,最終導致整個項目的失敗。3.4.1. 抵御新技術的誘惑架構師必須明白,新技術常常意味著復雜和更低的性能。即使這不是絕對的,由于嵌入式系統(tǒng)硬件性能所限,彈性較低。一旦發(fā)現(xiàn)新技術有和當初設想不同之處,就更難通過修改來適應。比如GWT技術。這是Google推出的Ajax開發(fā)工具,它可以讓程序員像開發(fā)一個桌面應用程序一樣開發(fā)Web的Ajax程序。這使得在嵌入式系統(tǒng)上用一套代碼實現(xiàn)遠程和本地操作界面成為了很容易的一件事。但是在嵌入式設備上運行B-S結

22、構的應用,性能上是一個很大的挑戰(zhàn)。同時,瀏覽器兼容方面的問題也很嚴重,GWT目前的版本還不夠完善。事實證明,嵌入式的遠程控制方案還是要采用Activex,VNC或者其他的方案。3.4.2. 不要有太多的層次分層結構有利于清晰的劃分系統(tǒng)職責,實現(xiàn)系統(tǒng)的解耦,但是每多一個層次,就意味著性能的一次損失。尤其是當層和層之間需要傳遞大量數(shù)據(jù)的時候。對嵌入式系統(tǒng)而言,在采用分層結構時要控制層次數(shù)量,并且盡量不要傳遞大量數(shù)據(jù),尤其是在不同進程的層次之間。如果一定要傳遞數(shù)據(jù),要避免大量的數(shù)據(jù)格式轉(zhuǎn)換,如XML到二進制,C+結構到Python結構。嵌入式系統(tǒng)能力有限,一定要將有限的能力用在系統(tǒng)的核心功能上。3.

23、5. 存儲設備易損壞,速度較慢受體積和成本的限制,大部分的嵌入式設備使用諸如Compact Flash, SD, mini SD, MMC等作為存儲設備。這些設備雖然有著不擔心機械運動損壞的優(yōu)點,但是其本身的使用壽命都比較短暫。比如,CF卡一般只能寫100萬次。而SD更短,只有10萬次。對于像數(shù)碼相機這樣的應用,也許是足夠的。但是對于需要頻繁擦寫磁盤的應用,比如歷史數(shù)據(jù)庫,磁盤的損壞問題會很快顯現(xiàn)。比如有一個應用式每天向CF卡上寫一個16M的文件,文件系統(tǒng)是FAT16, 每簇大小是2K,那么寫完這個16M的文件,分區(qū)表需要寫8192次,于是一個100萬次壽命的CF實際能夠工作的時間是10000

24、00/8192 = 122天。而損壞的時候,CF卡的其他絕大部分地方的使用次數(shù)不過萬分之一。除了因為靜態(tài)的文件分區(qū)表等區(qū)塊被頻繁的讀寫而提前損壞,一些嵌入式設備還要面對直接斷電的挑戰(zhàn),這會在存儲設備上產(chǎn)生不完整的數(shù)據(jù)。3.5.1. 損耗均衡損耗均衡的基本思路是平均地使用存儲器上的各個區(qū)塊。需要維護一張存儲器區(qū)塊使用情況的表,這個表包括區(qū)塊的偏移位置,當前是否可用,以及已經(jīng)擦寫地次數(shù)。當有新的擦寫請求的時候,根據(jù)以下原則選擇區(qū)塊:1. 盡量連續(xù)2. 擦寫次數(shù)最少即使是更新已經(jīng)存在的數(shù)據(jù),也會使用以上原則分配新的區(qū)塊。同樣,這張表的存放位置也不能是固定不變的,否則這張表所占據(jù)的區(qū)塊就會最先損壞。當

25、要更新這張表的時候,同樣要使用以上算法分配區(qū)塊。如果存儲器上有大量的靜態(tài)數(shù)據(jù),那么上述算法就只能針對剩下的空間生效,這種情況下還要實現(xiàn)對這些靜態(tài)數(shù)據(jù)的搬運的算法。但是這種算法會降低寫操作的性能,也增加了算法的復雜度。一般都只使用動態(tài)均衡算法。目前比較成熟的損耗均衡的文件系統(tǒng)有JFFS2, 和 YAFFS。也有另一種思路就是在FAT16等傳統(tǒng)文件系統(tǒng)上實現(xiàn)損耗均衡,只要事先分配一塊足夠大的文件,在文件內(nèi)部實現(xiàn)損耗均衡算法。不過必須修改FAT16的代碼,關閉對最后修改時間的更新。現(xiàn)在的CF卡和SD卡有的已經(jīng)在內(nèi)部實現(xiàn)了損耗均衡,這種情況下就不需要軟件實現(xiàn)了。3.5.2. 錯誤恢復如果在向存儲器寫數(shù)

26、據(jù)的時候發(fā)生斷電或者被拔出,那么所寫的區(qū)域的數(shù)據(jù)就處于未知的狀態(tài)。在一些應用中,這會導致不完整的文件,而在另一些應用中,則會導致系統(tǒng)失敗。所以對這類錯誤的恢復也是嵌入式軟件設計必須考慮的。常用的思路有兩種:1. 日志型的文件系統(tǒng)這種文件系統(tǒng)并不是直接存儲數(shù)據(jù),而是一條條的日志,所以當發(fā)生斷電的時候,總可以恢復到之前的狀態(tài)。這類文件系統(tǒng)的代表如ext3。2. 雙備份雙備份的思路更簡單,所有的數(shù)據(jù)都寫兩份。每次交替使用。文件分區(qū)表也必須是雙備份的。假設有數(shù)據(jù)塊A,A1是他的備份塊,在初始時刻和A的內(nèi)容是一致的。在分區(qū)表中,F(xiàn)指向數(shù)據(jù)塊A,F(xiàn)1是他的備份塊。當修改文件時,首先修改數(shù)據(jù)塊A1的內(nèi)容,如

27、果此時斷電,A1的內(nèi)容錯誤,但因為F指向的是完好的A,所以數(shù)據(jù)沒有損壞。如果A1修改成功,則修改F1的內(nèi)容,如果此時斷電,因為F是完好的,所以依然沒有問題。現(xiàn)在的Flash設備,有的已經(jīng)內(nèi)置錯誤檢測和錯誤校正技術,可以保證在斷電時數(shù)據(jù)的完整。還有的包括自動的動態(tài)/靜態(tài)損耗均衡算法和壞塊處理,完全無須上層軟件額外對待,可以當作硬盤使用。所以,硬件越發(fā)達,軟件就會越可靠,技術不斷的進步,將讓我們可以把更多的精力投入到軟件功能的本身,這是發(fā)展的趨勢。3.6. 故障成本高昂嵌入式產(chǎn)品都是軟硬件一起銷售的給用戶的,所以這帶來了一個純軟件所不具備的問題,那就是當產(chǎn)品發(fā)生故障時,如果需要返廠才能修復,則成本

28、就很高。嵌入式設備常見有以下的幾類故障:a) 數(shù)據(jù)故障。由于某些原因?qū)е聰?shù)據(jù)不能讀出或者不一致。比如斷電引起的數(shù)據(jù)庫錯誤。b) 軟件故障。軟件本身的缺陷,需要通過發(fā)布補丁程序或者新版本的軟件修正。c) 系統(tǒng)故障。比如用戶下載了錯誤的系統(tǒng)內(nèi)核,導致系統(tǒng)無法啟動。d) 硬件故障。這種故障只有返廠,不屬于我們的討論范圍。針對前三類故障,要盡可能保證客戶自己,或者現(xiàn)場技術人員就可以解決。從架構的角度考慮,如下原則可以參考:a) 使用具備錯誤恢復能力的數(shù)據(jù)管理設計。當數(shù)據(jù)發(fā)生錯誤時,用戶可以接受的處理依次是:i. 錯誤被糾正,所有數(shù)據(jù)有效ii. 錯誤發(fā)生時的數(shù)據(jù)(可能不完整)丟失,之前的數(shù)據(jù)有效。iii

29、. 所有數(shù)據(jù)丟失iv. 數(shù)據(jù)引擎崩潰無法繼續(xù)工作一般而言,滿足第二個條件即可。(日志,事務,備份,錯誤識別)b) 將應用程序和系統(tǒng)分離。應用程序應該放置在可插拔的Flash卡上,可以通過讀卡器進行文件復制升級。非必要的情況不要使用專用應用軟件來升級應用程序。c) 要有“安全模式”。即當主系統(tǒng)被損壞后,設備依然可以啟動,重新升級系統(tǒng)。常見的uboot可以保證這一點,在系統(tǒng)損壞后,可以進入uboot通過tftp重新升級。4. 軟件框架在桌面系統(tǒng)和網(wǎng)絡系統(tǒng)上,框架是普遍應用的,比如著名的ACE, MFC, Ruby On Rails等。而在嵌入式系統(tǒng)中,框架則是很少使用的。究其原因,大概是認為嵌入式

30、系統(tǒng)簡單,沒有重復性,過于注重功能的實現(xiàn)和性能的優(yōu)化。在前言中我們已經(jīng)提到,現(xiàn)在的嵌入式發(fā)展趨勢是向著復雜化,大型化,系列化發(fā)展的。所以,在嵌入式下設計軟件框架也是很有必要,也很有價值的。4.1. 嵌入式軟件架構面臨的問題前面我們講到,嵌入式系統(tǒng)軟件架構所面臨的一些問題,其中很重要的一點是,對硬件的依賴和硬件相關軟件的復雜性。還包括嵌入式軟件在穩(wěn)定性和內(nèi)存占用等方面的苛刻要求。如果團隊中的每個人都是這些方面高手的話,也許有可能開發(fā)出高質(zhì)量的軟件,但事實是一個團隊中可能只有一兩個資深人員,其他大部分都是初級工程師。人人都去和硬件打交道,都負責穩(wěn)定性,性能等等指標的話,是很難保證最終產(chǎn)品質(zhì)量的。如

31、果組件團隊時都是精通硬件等底層技術的人才,又很難設計出在可用性,擴展性等方面出色的軟件。術業(yè)有專攻,架構師的選擇決定著團隊的組成方式。同時,嵌入式軟件開發(fā)雖然復雜,但是也存在大量的重用的可能性。如何重用,又如何應對將來的變更?所以,如何將復雜性對大多數(shù)人屏蔽,如何將關注點分離,如何保證系統(tǒng)的關鍵非功能指標,是嵌入式軟件架構設計師應該解決的問題。一種可能的解決方案就是軟件框架。4.2. 什么是框架框架是在一個給定的問題領域內(nèi),為了重用和應對未來需求變化而設計的軟件半成品。框架強調(diào)對特定領域的抽象,包含大量的專業(yè)領域知識,以縮短軟件的開發(fā)周期,提高軟件質(zhì)量為目的。使用框架的二次開發(fā)者通過重寫子類或

32、組裝對象的方式來實現(xiàn)特殊的功能。4.2.1. 軟件復用的層次復用是在我們經(jīng)常談到的話題,“不要重復發(fā)明輪子”也是耳熟能詳?shù)慕錀l。不過對于復用的理解實際上是有很多個層次的。最基礎的復用是復制粘貼。某個功能以前曾經(jīng)實現(xiàn)過,再次需要的時候就復制過來,修改一下就可以使用。經(jīng)驗豐富的程序員一般都會有自己的程序庫,這樣他們實現(xiàn)的時候就會比新的程序員快。復制粘貼的缺點是代碼沒有經(jīng)過抽象,往往并不完全的適用,所以需要進行修改,經(jīng)過多次復用后,代碼將會變得混亂,難以理解。很多公司的產(chǎn)品都有這個問題,一個產(chǎn)品的代碼從另一個產(chǎn)品復制而來,修改一下就用,有時候甚至類名變量名都不改。按照“只有為復用設計的代碼才能真正復

33、用”的標準,這稱不上是復用,或者說是低水平的復用。更高級的復用是則是庫。這種功能需要對經(jīng)常使用的功能進行抽象,提取出其中恒定不變的部分,以庫的形式提供給二次開發(fā)程序員使用。因為設計庫的時候不知道二次開發(fā)者會如何使用,所以對設計者有著很高的要求。這是使用最廣泛的一種復用,比如標準C庫,STL庫?,F(xiàn)在非常流行的Python語言的重要優(yōu)勢之一就是其庫支持非常廣泛,相反C+一直缺少一個強大統(tǒng)一的庫支持,成為短板。在公司內(nèi)部的開發(fā)中總結常用功能并開發(fā)成庫是很有價值的,缺點是對庫的升級會影響到很多的產(chǎn)品,必須慎之又慎。框架是另一種復用。和庫一樣,框架也是對系統(tǒng)中不變的部分進行抽象并加以實現(xiàn),由二次開發(fā)者實

34、現(xiàn)其他變化的部分。典型的框架和庫的最大的區(qū)別是,庫是靜態(tài)的,由二次開發(fā)者調(diào)用的;框架是活著的,它是主控者,二次開發(fā)者的代碼必須符合框架的設計,由框架決定在何時調(diào)用。舉個例子,一個網(wǎng)絡應用總是要涉及到連接的建立,數(shù)據(jù)收發(fā)和連接的關閉。以庫的形式提供是這樣的:conn = connect(host,port);if(conn.isvalid()data = conn.recv();printf(data);conn.close();框架則是這樣的:class mycomm:class connectpublic:host();port();onconnected();ondataarrived(u

35、nsigned char* data, int len);onclose();框架會在“適當”的時機創(chuàng)建mycomm對象,并查詢host和port,然后建立連接。在連接建立后,調(diào)用onconnected()接口,給二次開發(fā)者提供進行處理的機會。當數(shù)據(jù)到達的時候調(diào)用ondataarrived接口讓二次開發(fā)者處理。這是好萊塢原則,“不要來找我們,我們會去找你”。當然,一個完整的框架通常也要提供各種庫供二次開發(fā)者使用。比如MFC提供了很多的庫,如CString, 但本質(zhì)上它是一個框架。比如實現(xiàn)一個對話框的OnInitDialog接口,就是由框架規(guī)定的。4.2.2. 針對高度特定領域的抽象和庫比較起來

36、,框架是更針對特定領域的抽象。庫,比如C庫,是面向所有的應用的。而框架相對來說則要狹窄的多。比如MFC提供的框架只適合于Windows平臺的桌面應用程序開發(fā),ACE則是針對網(wǎng)絡應用開發(fā)的框架,Ruby On Rails是為快速開發(fā)web站點設計的。越是針對特定的領域,抽象就可以做的越強,二次開發(fā)就可以越簡單,因為共性的東西越多。比如我們上面談到嵌入式系統(tǒng)軟件開發(fā)的諸多特點,這就是特定領域的共性,就屬于可以抽象的部分。具體到實際的嵌入式應用,又會有更多的共性可以抽象??蚣艿脑O計目的是總結特定領域的共性,以框架的方式實現(xiàn),并規(guī)定二次開發(fā)者的實現(xiàn)方式,從而簡化開發(fā)。相應的,針對一個領域開發(fā)的框架就不

37、能服務于另一個領域。對企業(yè)而言,框架是一種極好的積累知識,降低成本的技術手段。4.2.3. 解除耦合和應對變化框架設計的一個重要目的就是應對變化。應對變化的本質(zhì)就是解耦。從架構師的角度看,解耦可以分為三種:1. 邏輯解耦。邏輯解耦是將邏輯上不同的模塊抽象并分離處理。如數(shù)據(jù)和界面的解耦。這也是我們最常做的解耦。2. 知識解耦。知識解耦是通過設計讓掌握不同知識的人僅僅通過接口工作。典型的如測試工程師所掌握的專業(yè)知識和開發(fā)工程師所掌握的程序設計和實現(xiàn)的知識。傳統(tǒng)的測試腳本通常是將這二者合二為一的。所以要求測試工程師同時具備編程的能力。通過適當?shù)姆绞剑梢宰寽y試工程師以最簡單的方式實現(xiàn)他的測試用例,而

38、開發(fā)人員編寫傳統(tǒng)的程序代碼來執(zhí)行這些用例。3. 變與不變的解耦。這是框架的重要特征??蚣芡ㄟ^對領域知識的分析,將共性,也就是不變的內(nèi)容固定下來,而將可能發(fā)生變化的部分交給二次開發(fā)者實現(xiàn)。4.2.4. 框架可以實現(xiàn)和規(guī)定非功能性需求非功能性需求是指如性能,可靠性,可測試性,可移植性等。這些特性可以通過框架來實現(xiàn)。以下我們一一舉例。性能。對性能的優(yōu)化最忌諱的就是普遍優(yōu)化。系統(tǒng)的性能往往取決于一些特定的點。比如在嵌入式系統(tǒng)中,對存儲設備的訪問是比較慢的。如果開發(fā)者不注意這方面的問題,頻繁的讀寫存儲設備,就會造成性能下降。如果對存儲設備的讀寫由框架設計,二次開發(fā)者只作為數(shù)據(jù)的提供和處理者,那么就可以在

39、框架中對讀寫的頻率進行調(diào)節(jié),從而達到優(yōu)化性能的目的。由于框架都是單獨開發(fā)的,完成后供廣泛使用,所以就有條件對關鍵的性能點進行充分的優(yōu)化。可靠性。以上面的網(wǎng)絡通訊程序為例,由于框架負責了連接的創(chuàng)建和管理,也處理了各種可能的網(wǎng)絡錯誤,具體的實現(xiàn)者無須了解這方面的知識,也無須實現(xiàn)這方面錯誤處理的代碼,就可以保證整個系統(tǒng)在網(wǎng)絡通訊方面的可靠性。以框架的方式設計在可靠性方面的最大優(yōu)勢就是:二次開發(fā)的代碼是在框架的掌控之內(nèi)運行的。一方面框架可以將容易出錯的部分實現(xiàn),另一方面對二次開發(fā)的代碼產(chǎn)生的錯誤也可以捕獲和處理。而庫則不能代替使用者處理錯誤??蓽y試性??蓽y試性是軟件架構需要考慮的一個重要方面。下面的章

40、節(jié)會講到,軟件的可測試性是由優(yōu)良的設計來保證的。一方面,由于框架規(guī)定了二次開發(fā)的接口,所以可以迫使二次開發(fā)者開發(fā)出便于進行單元測試的代碼。另一方面,框架也可以在系統(tǒng)測試的層面上提供易于實現(xiàn)自動化測試和回歸測試的設計,例如統(tǒng)一提供的TL1接口。可移植性。如果軟件的可移植性是軟件設計的目標,框架設計者可以在設計階段來保證這一點。一種方式是通過跨平臺的庫來屏蔽系統(tǒng)差異,另一種可能的方式更加極端,基于框架的二次開發(fā)可以是腳本化的。組態(tài)軟件是這方面的一個例子,在PC上組態(tài)的工程,也可以在嵌入式設備上運行。4.3. 一個框架設計的實例4.3.1. 基本架構軟件 WinCE,ARM芯片,觸摸屏,圖形化界面,

41、 Lua腳本界面硬件 各種具體硬件,如ADSL測試芯片,VOIP測試芯片,可插拔替換固件 pSOS實時系統(tǒng), MIPS芯片USB 2.0對外提供XML,TL1接口4.3.2. 功能特點上面是一個產(chǎn)品系列的架構圖,其特點是硬件部分是模塊化的,可以隨時插拔。不同的硬件應用于不同的通訊測試場合。比如光通訊測試,xDSL測試,Cable Modem測試等等。針對不同的硬件,需要開發(fā)不同的固件和軟件。固件層的功能主要是通過USB接口接收來自軟件的指令,并讀寫相應的硬件接口,再進行一些計算后,將結果返回給軟件。軟件運行在WinCE平臺,除了提供一個觸摸式的圖形化界面外,還對外提供基于XML(SOAP)接口

42、和TL1接口。為了實現(xiàn)自動化測試,還提供了基于Lua的腳本語言接口。整個產(chǎn)品系列有幾十個不同的硬件模塊,相應的需要開發(fā)幾十套軟件。這些軟件雖然服務于不同的硬件,但是彼此之間有著高度的相似性。所以,選擇先開發(fā)一個框架,再基于框架開發(fā)具體的模塊軟件成了最優(yōu)的選擇。4.3.3. 分析軟件部分的結構分析如下:協(xié)議層圖形界面TL1 Server內(nèi)存數(shù)據(jù)庫通訊層SOAP ServerTerm/scriptSOAP Client硬件通訊層任務1任務2任務任務n硬件抽象層(FPGA/IOBoard.)派發(fā)器協(xié)議層視圖系統(tǒng)分為軟件,固件和硬件三大塊。軟件和固件運行在兩塊獨立的板子上,有各自的處理器和操作系統(tǒng)。硬

43、件則插在固件所在的板子上,是可以替換的。軟件和固件其實都是軟件,下面我們分別分析。軟件軟件的主要工作是提供各種用戶界面。包括本地圖形化界面,SOAP訪問界面,TL1訪問界面。整個軟件部分分為五大部分:通訊層協(xié)議層圖形界面SOAP服務器TL1服務器通訊層要屏蔽用戶對具體通信介質(zhì)和協(xié)議的了解,無論是USB還是socket,對上層都不產(chǎn)生影響。通訊層負責提供可靠的通訊服務和適當?shù)腻e誤處理。通過配置文件,用戶可以改變所使用的通訊層。協(xié)議層的目的是將數(shù)據(jù)進行編碼和解碼。編碼的產(chǎn)生物是可以在通訊層發(fā)送的流,按照嵌入式軟件的特點,我們選擇二進制作為流的格式。解碼的產(chǎn)生物是多種的,既有供界面使用的C Stru

44、ct,也可以是XML數(shù)據(jù),還可以是Lua的數(shù)據(jù)結構(tablegt)。如果需要,還可以產(chǎn)生JSON,TL1,Python數(shù)據(jù),TCL數(shù)據(jù)等等。這一層在框架中是通過機器自動生成的,我們后面會講到。內(nèi)存數(shù)據(jù)庫,SOAP Server和TL1 Server都是協(xié)議層的用戶。圖形界面通過讀寫內(nèi)存數(shù)據(jù)庫和底層通訊。圖形界面是框架設計的重點之一,原因是這里工作量最大,重復而無聊的工作最多。讓我們分析一下在圖形界面開發(fā)工作中最主要的事情是什么。1. 收集用戶輸入的數(shù)據(jù)和命令2. 將數(shù)據(jù)和命令發(fā)給底層3. 接收底層反饋4. 將數(shù)據(jù)顯示在界面上同時有一些庫用來進一步簡化開發(fā):這是一個簡化的例子,但是很好的說明了

45、框架的特點:1. 客戶代碼必須按照規(guī)定的接口實現(xiàn)2. 框架在適當?shù)臅r候調(diào)用客戶實現(xiàn)的接口3. 每個接口都被設計為只完成特定的單一功能4. 將各個步驟有機的串起來是框架的事,二次開發(fā)者不知道,也無須知道。5. 通常都要有附帶的庫。固件固件的主要工作是接受來自軟件的命令,驅(qū)動硬件工作;獲取硬件的狀態(tài),進行一定的計算后返回給軟件。早期的固件是很薄的一層,因為絕大部分工作是由硬件完成的,固件只起到一個中轉(zhuǎn)通訊的作用。隨著時代發(fā)展,現(xiàn)在的固件開始承擔越來越多原來由硬件完成的工作。整個固件部分分為五大部分:硬件抽象層,提供對硬件的訪問接口互相獨立的任務群任務/消息派發(fā)器協(xié)議層通訊層針對不同的設備,工作量集

46、中在硬件抽象層和任務群上。硬件抽象層是以庫的形式提供的,由對硬件最熟悉,經(jīng)驗最豐富的工程師來實現(xiàn)。任務群則由一系列的任務組成,他們分別代表不同的業(yè)務應用。比如測量誤碼率。這部分由相對經(jīng)驗較少的工程師來實現(xiàn),他們的主要工作是實現(xiàn)規(guī)定的接口,按照標準化文檔定義的方式實現(xiàn)算法。任務定義了如下接口,由具體開發(fā)者來實現(xiàn):OnInit();OnRegisterMessage();OnMessageArrive();Run();OnResultReport();框架的代碼流程如下:(偽代碼)CTask* task = new CBertTask();task->OnInit();task->On

47、RegisterMessage();while(TRUE)task->OnMessageArrive();task->Run();task->OnResultReport();delete task;task = NULL;這樣,具體任務的實現(xiàn)者所關注的最重要的事情就是實現(xiàn)這幾個接口。其他如硬件的初始化,消息的收發(fā),編碼解碼,結果的上報等等事情都由框架進行了處理。 避免了每個工程師都必須處理從上到下的所有方面。并且這樣的任務代碼還有很高的重用性,比如是在以太網(wǎng)上還是在Cable Modem上實現(xiàn)PING的算法都是一樣的。4.3.4. 實際效果在實際項目中,框架大大降低了開發(fā)難

48、度。對軟件部分尤其明顯,由實習生即可完成高質(zhì)量的界面開發(fā),開發(fā)周期縮短50%以上。產(chǎn)品質(zhì)量大大提升。對固件部分的貢獻在于降低了對精通底層硬件的工程師的需要,一般的工程師熟知測量算法即可。同時,框架的存在保證了性能,穩(wěn)定和可測試性等要素。4.4. 框架設計中的常用模式4.4.1. 模板方法模式模板方法模式是框架中最常用的設計模式。其根本的思路是將算法由框架固定,而將算法中具體的操作交給二次開發(fā)者實現(xiàn)。例如一個設備初始化的邏輯,框架代碼如下:TBool CBaseDevice:Init()if (DownloadFPGA() != KErrNone) LOG(LOG_ERROR,_L(“Downl

49、oad FPGA fail”); return EFalse; if ( InitKeyPad() != KerrNone)LOG(LOG_ERROR,_L(“Initialize keypad fail”); return EFalse;return ETrue;DownloadFPGA和InitKeyPad都是CBaseDevice定義的虛函數(shù),二次開發(fā)者創(chuàng)建一個繼承于CBaseDevice的子類,具體來實現(xiàn)這兩個接口??蚣芏x了調(diào)用的次序和錯誤的處理方式,二次開發(fā)者無須關心,也無權決定。4.4.2. 創(chuàng)建型模式由于框架通常都涉及到各種不同子類對象的創(chuàng)建,創(chuàng)建型模式是經(jīng)常使用的。例如一個繪

50、圖軟件的框架,有一個基類定義了圖形對象的接口,基于它可以派生出橢圓,矩形,直線各種子類。當用戶繪制一個圖形時,框架就要實例化該子類。這時候可以用工廠方法,原型方法等等。class CDrawObjpublic:virtual int DrawObjTypeID()=0;virtual Icon GetToolBarIcon()=0;virtual void Draw(Rect rect)=0;virtual CDrawObj* Clone()=0;4.4.3. 消息訂閱模式消息訂閱模式是最常用的分離數(shù)據(jù)和界面的方式。界面開發(fā)者只需要注冊需要的數(shù)據(jù),當數(shù)據(jù)變化時框架就會將數(shù)據(jù)“推”到界面。界面開

51、發(fā)者可以無須關注數(shù)據(jù)的來源和內(nèi)部組織形式。消息訂閱模式最常見的問題是同步模式下如何處理重入和超時。作為框架設計者,一定要考慮好這個問題。所謂重入,是二次開發(fā)者在消息的回調(diào)函數(shù)中執(zhí)行訂閱/取消訂閱的操作,這會破壞消息訂閱的機制。所謂超時是指二次開發(fā)者的消息回調(diào)函數(shù)處理時間過長,導致其他消息無法響應。最簡單的辦法是使用異步模式,讓訂閱者和數(shù)據(jù)發(fā)布者在獨立進程/線程中運行。如果不具備此條件,則必須作為框架的重要約定,禁止二次開發(fā)者產(chǎn)生此類問題。4.4.4. 裝飾器模式裝飾器模式賦予了框架在后期增加功能的能力。框架定義裝飾器的抽象基類,而由具體的實現(xiàn)者實現(xiàn),動態(tài)地添加到框架中。舉一個游戲中的例子,圖形

52、繪制引擎是一個獨立的模塊,比如可以繪制人物的靜止,跑動等圖像。如果策劃決定在游戲中增加一種叫“隱身衣”的道具,要求穿著此道具的玩家在屏幕上顯示的是若有若無的半透明圖像。應該如何設計圖像引擎來適應后期的游戲升級呢?當隱身衣被裝備后,就向圖像引擎添加一個過濾器。這是個極度簡化的例子,實際的游戲引擎要比這個復雜。裝飾器模式還常見用于數(shù)據(jù)的前置和后置處理上。4.5. 框架的缺點一個好的框架可以大大提高產(chǎn)品的開發(fā)效率和質(zhì)量,但也有它的缺點。1. 框架一般都比較復雜,設計和實現(xiàn)一個好的框架需要相當?shù)臅r間。所以,一般只有在框架可以被多次反復應用的時候適合,這時候,前提投入的成本會得到豐厚的回報。2. 框架規(guī)

53、定了一系列的接口和規(guī)則,這雖然簡化了二次開發(fā)工作,但同時也要求二次開發(fā)者必須記住很多規(guī)定,如果違反了這些規(guī)定,就不能正常工作。但是由于框架屏蔽了大量的領域細節(jié),相對而言,其學習成本還是大大降低了的。3. 框架的升級對已有產(chǎn)品可能會造成嚴重的影響,導致需要完整的回歸測試。對這個問題有兩個辦法。第一是對框架本身進行嚴格的測試,有必要建立完善的單元測試庫,同時開發(fā)示例項目,用來測試框架的所有功能。第二則是使用靜態(tài)鏈接,讓已有產(chǎn)品不輕易跟隨升級。當然,如果已有產(chǎn)品有較好的回歸測試手段,就更好。4. 性能損失。由于框架對系統(tǒng)進行了抽象,增加了系統(tǒng)的復雜性。諸如多態(tài)這樣的手段使用也會普遍的降低系統(tǒng)的性能。

54、但是從整體上來看,框架可以保證系統(tǒng)的性能處于一個較高的水平。5. 自動代碼生成5.1. 機器能做的事就不要讓人來做懶惰是程序員的美德,更是架構師的美德。軟件開發(fā)的過程就是人告訴機器如何做事的過程。如果一件事情機器自己就可以做,那就不要讓人來做。因為機器不僅不知疲倦,而且絕不會犯錯。我們的工作是讓客戶的工作自動化,多想一點,就能讓我們自己的工作也部分自動化。極有耐心的程序員是好的,也是不好的。經(jīng)過良好設計的系統(tǒng),往往會出現(xiàn)很多高度類似而且具有很強規(guī)律的代碼。未經(jīng)良好設計的系統(tǒng)則可能對同一類功能產(chǎn)生很多不同的實現(xiàn)。前面關于框架設計的部分已經(jīng)證明了這一點。有時候,我們更進一步,分析出這些相似代碼之中

55、的規(guī)律,用格式化的數(shù)據(jù)來描述這些功能,而由機器來產(chǎn)生代碼。5.2. 舉例5.2.1. 消息的編碼和解碼上面關于框架的實例中,可以看到消息編解碼的部分已經(jīng)被獨立出來,和其他部分沒有耦合。加上他本身的特點,非常適合進一步將其“規(guī)則化”,用機器產(chǎn)生代碼。編碼,就是把數(shù)據(jù)結構流化;解碼反之。以編碼為例,代碼無非是這樣的:(二進制協(xié)議)stream << a.i;stream << a.j;stream << a.object;(為了簡化,這里假設已經(jīng)設計了一個流對象,可以流化各種數(shù)據(jù)類型,并且已經(jīng)處理了諸如字節(jié)序轉(zhuǎn)換等問題。)最后我們得到一個stream。大家是否已

56、經(jīng)習慣了寫這種代碼?但是這樣的代碼不能體現(xiàn)工程師任何的創(chuàng)造性,因為我們早已經(jīng)知道有i, 有j, 還有一個object,為什么還要自己敲入這些代碼呢?如果我們分析一下a的定義,是不是就可以自動產(chǎn)生這樣的代碼呢?struct dataAint i;int j;struct dataB object;只需要一個簡單的語義分析器解析這段代碼,得到一棵關于數(shù)據(jù)類型的樹,就可以輕易的產(chǎn)生流化的代碼。這樣的分析器用Python等字符串處理能力強的語言不過兩百行左右。關于數(shù)據(jù)類型的樹類似下圖:struct dataAi:intobject:struct dataBi:intstruct dataBname:s

57、tringids:intarrayTypes只要遍歷這棵樹,就可以生成所有數(shù)據(jù)結構的流化代碼。在上一個框架所舉例的項目中,為一個硬件模塊自動產(chǎn)生的消息編碼解碼器代碼量高達三萬行,幾乎相當于一個小軟件。由于是自動產(chǎn)生,沒有任何錯誤,為上層提供了高可靠性。還可以用XML或者其他的格式定義數(shù)據(jù)結構,從而產(chǎn)生自動代碼。根據(jù)需要,C+/Java/Python,任何類型的都可以。如果希望提供強檢查,可以使用XSD來定義數(shù)據(jù)結構。有一個商業(yè)化的產(chǎn)品,xBinder,很貴,很難用,還不如自己開發(fā)。(為什么難用?因為它太通用)。除了編碼為二進制格式,還可以編碼為任何你需要的格式。我們知道二進制格式雖然效率很高,但是太難調(diào)試(當然有些人看內(nèi)存里的十六進制還是很快的),所以我們可以在編碼成二進制的同時,還生成編碼為其他可閱讀的格式的代碼,比如XML。這樣,通訊使用二進制,而調(diào)試使用XML,兩全其美。產(chǎn)生二進制的代碼大概是這樣的:Xmlbuilder.addelement(“i”,a.i);Xmlbuilder.addelement(“j”,a.j)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論