嵌入式Linux開發
嵌入式Linux的開發和研究是Linux領域研究的一個熱點,目前已開發成功的嵌入式系統有一半以上都是Linux。Linux到底有什么優勢,使之取得如此輝煌的成績呢?本文分為兩大部分:Linux的優點、Linux開發。
一、Linux的優勢:
廣泛的硬件支持
Linux能夠支持x86、ARM、MIPS、ALPHA、PowerPC等多種體系結構,目前已經成功移植到數十種硬件平臺,幾乎能夠運行在所有流行的CPU上。Linux有著異常豐富的驅動程序資源,支持各種主流硬件設備和***硬件技術,甚至可以在沒有存儲管理單元(MMU)的處理器上運行,這些都進一步促進了Linux在嵌入式系統中的應用。
內核高效穩定
Linux內核的高效和穩定已經在各個領域內得到了大量事實的驗證,Linux的內核設計非常精巧,分成進程調度、內存管理、進程間通信、虛擬文件系統和網絡接口五大部分,其獨特的模塊機制可以根據用戶的需要,實時地將某些模塊插入到內核或從內核中移走。這些特性使得Linux系統內核可以裁剪得非常小巧,很適合于嵌入式系統的需要。
開放源碼,軟件豐富
Linux是開放源代碼的自由操作系統,它為用戶提供了***限度的自由度,由于嵌入式系統千差萬別,往往需要針對具體的應用進行修改和優化,因而獲得源代碼就變得至關重要了。Linux的軟件資源十分豐富,每一種通用程序在Linux上幾乎都可以找到,并且數量還在不斷增加。在Linux上開發嵌入式應用軟件一般不用從頭做起,而是可以選擇一個類似的自由軟件做為原型,在其上進行二次開發。
優秀的開發工具
開發嵌入式系統的關鍵是需要有一套完善的開發和調試工具。傳統的嵌入式開發調試工具是在線仿真器(In-Circuit Emulator,ICE),它通過取代目標板的微處理器,給目標程序提供一個完整的仿真環境,從而使開發者能夠非常清楚地了解到程序在目標板上的工作狀態,便于監視和調試程序。在線仿真器的價格非常昂貴,而且只適合做非常底層的調試,如果使用的是嵌入式Linux,一旦軟硬件能夠支持正常的串口功能時,即使不用在線仿真器也可以很好地進行開發和調試工作,從而節省了一筆不小的開發費用。嵌入式Linux為開發者提供了一套完整的工具鏈(Tool Chain),它利用GNU的gcc做編譯器,用gdb、kgdb、xgdb做調試工具,能夠很方便地實現從操作系統到應用軟件各個級別的調試。
完善的網絡通信和文件管理機制
Linux至誕生之日起就與Internet密不可分,支持所有標準的Internet網絡協議,并且很容易移植到嵌入式系統當中。此外,Linux還支持ext2、fat16、fat32、romfs等文件系統,這些都為開發嵌入式系統應用打下了很好的基礎。
二、嵌入式Linux開發技術:
嵌入式系統是一種根據特定用途所專門開發的系統,它只完成預期要完成的功能,因此其開發過程和開發環境同傳統的軟件開發相比有著顯著的不同。
1.開發流程
在嵌入式系統的應用開發中,整個系統的開發過程如圖2所示:
圖2 嵌入式系統的開發流程
嵌入式系統發展到今天,對應于各種微處理器的硬件平臺一般都是通用的、固定的、成熟的,這就大大減少了由硬件系統引入錯誤的機會。此外,由于嵌入式操作系統屏蔽了底層硬件的復雜性,使得開發者通過操作系統提供的API函數就可以完成大部分工作,因此大大簡化了開發過程,提高了系統的穩定性。嵌入式系統的開發者現在已經從反復進行硬件平臺設計的過程中解脫出來,從而可以將主要精力放在滿足特定的需求上。
嵌入式系統通常是一個資源受限的系統,因此直接在嵌入式系統的硬件平臺上編寫軟件比較困難,有時候甚至是不可能的。目前一般采用的解決辦法是首先在通用計算機上編寫程序,然后通過交叉編譯生成目標平臺上可以運行的二進制代碼格式,***再下載到目標平臺上的特定位置上運行。
需要交叉開發環境(Cross Development Environment)的支持是嵌入式應用軟件開發時的一個顯著特點,交叉開發環境是指編譯、鏈接和調試嵌入式應用軟件的環境,它與運行嵌入式應用軟件的環境有所不同,通常采用宿主機/目標機模式,如圖3所示。
圖3 交叉開發環境
宿主機(Host)是一臺通用計算機(如PC機或者工作站),它通過串口或者以太網接口與目標機通信。宿主機的軟硬件資源比較豐富,不但包括功能強大的操作系統(如Windows和Linux),而且還有各種各樣優秀的開發工具(如WindRiver的Tornado、Microsoft的Embedded Visual C++等),能夠大大提高嵌入式應用軟件的開發速度和效率。
目標機(Target)一般在嵌入式應用軟件開發期間使用,用來區別與嵌入式系統通信的宿主機,它可以是嵌入式應用軟件的實際運行環境,也可以是能夠替代實際運行環境的仿真系統,但軟硬件資源通常都比較有限。嵌入式系統的交叉開發環境一般包括交叉編譯器、交叉調試器和系統仿真器,其中交叉編譯器用于在宿主機上生成能在目標機上運行的代碼,而交叉調試器和系統仿真器則用于在宿主機與目標機間完成嵌入式軟件的調試。在采用宿主機/目標機模式開發嵌入式應用軟件時,首先利用宿主機上豐富的資源和良好的開發環境開發和仿真調試目標機上的軟件,然后通過串口或者以網絡將交叉編譯生成的目標代碼傳輸并裝載到目標機上,并在監控程序或者操作系統的支持下利用交叉調試器進行分析和調試,***目標機在特定環境下脫離宿主機單獨運行。
建立交叉開發環境是進行嵌入式軟件開發的***步,目前常用的交叉開發環境主要有開放和商業兩種類型。開放的交叉開發環境的典型代表是GNU工具鏈、目前已經能夠支持x86、ARM、MIPS、PowerPC等多種處理器。商業的交叉開發環境則主要有Metrowerks CodeWarrior、ARM Software Development Toolkit、SDS Cross compiler、WindRiver Tornado、Microsoft Embedded Visual C++等。
2. 交叉編譯和鏈接
在完成嵌入式軟件的編碼之后,需要進行編譯和鏈接以生成可執行代碼,由于開發過程大多是在使用Intel公司x86系列CPU的通用計算機上進行的,而目標環境的處理器芯片卻大多為ARM、MIPS、PowerPC、DragonBall等系列的微處理器,這就要求在建立好的交叉開發環境中進行交叉編譯和鏈接。
交叉編譯器和交叉鏈接器是能夠在宿主機上運行,并且能夠生成在目標機上直接運行的二進制代碼的編譯器和鏈接器。例如在基于ARM體系結構的gcc交叉開發環境中,arm-linux-gcc是交叉編譯器,arm-linux-ld是交叉鏈接器。通常情況下,并不是每一種體系結構的嵌入式微處理器都只對應于一種交叉編譯器和交叉鏈接器,比如對于M68K體系結構的gcc交叉開發環境而言,就對應于多種不同的編譯器和鏈接器。如果使用的是COFF格式的可執行文件,那么在編譯Linux內核時需要使用m68k-coff-gcc和m68k-coff-ld,而在編譯應用程序時則需要使用m68k-coff-pic-gcc和m68k-coff-pic-ld。
嵌入式系統在鏈接過程中通常都要求使用較小的函數庫,以便***產生的可執行代碼能夠盡可能地小,因此實際運用時一般使用經過特殊處理的函數庫。對于嵌入式Linux系統來講,功能越來越強、體積越來越大的C語言函數庫glibc和數學函數庫libm已經很難滿足實際的需要,因此需要采用它們的精化版本uClibc、uClibm和newlib等。
目前嵌入式的集成開發環境都支持交叉編譯和交叉鏈接,如WindRiver Tornado和GNU工具鏈等,編寫好的嵌入式軟件經過交叉編譯和交叉鏈接后通常會生成兩種類型的可執行文件:用于調試的可執行文件和用于固化的可執行文件。
3. 交叉調試
嵌入式軟件經過編譯和鏈接后即進入調試階段,調試是軟件開發過程中必不可少的一個環節,嵌入式軟件開發過程中的交叉調試與通用軟件開發過程中的調試方式有所差別。在通用軟件開發中,調試器與被調試的程序往往運行在同一臺計算機上,調試器是一個單獨運行著的進程,它通過操作系統提供的調試接口來控制被調試的進程。而在嵌入式軟件開發中,調試時采用的是在宿主機和目標機之間進行的交叉調試,調試器仍然運行在宿主機的通用操作系統之上,但被調試的進程卻是運行在基于特定硬件平臺的嵌入式操作系統中,調試器和被調試進程通過串口或者網絡進行通信,調試器可以控制、訪問被調試進程,讀取被調試進程的當前狀態,并能夠改變被調試進程的運行狀態。
交叉調試(Cross Debug)又常常被稱為遠程調試(Remote Debug),是一種允許調試器以某種方式控制目標機上被調試進程的運行方式,并具有查看和修改目標機上內存單元、寄存器以及被調試進程中變量值等各種調試功能的調試方式。一般而言,遠程調試過程的結構如圖4所示。
圖4遠程調試結構
嵌入式系統的交叉調試有多種方法,可以被細分成不同的層次,但一般都具有如下一些典型特點:
調試器和被調試進程運行在不同的機器上,調試器運行在PC或者工作站上(宿主機),而被調試的進程則運行在各種專業調試板上(目標機)。
調試器通過某種通信方式與被調試進程建立聯系,如串口、并口、網絡、DBM、JTAG或者專用的通信方式。
在目標機上一般會具備某種形式的調試代理,它負責與調試器共同配合完成對目標機上運行著的進程的調試。這種調試代理可能是某些支持調試功能的硬件設備(如DBI 2000),也可能是某些專門的調試軟件(如gdbserver)。
目標機可能是某種形式的系統仿真器,通過在宿主機上運行目標機的仿真軟件,整個調試過程可以在一臺計算機上運行。此時物理上雖然只有一臺計算機,但邏輯上仍然存在著宿主機和目標機的區別。
在嵌入式軟件開發過程中的調試方式有很多種,應根據實際的開發要求和條件進行選擇。就調試方法而言,嵌入式系統的交叉調試可以分為硬件調試和軟件調試兩種,前者使用仿真調試器協助調試過程,而后者則使用軟件調試器完成調試過程。
硬件調試
相對于軟件調試而言,使用硬件調試器可以獲得更強大的調試功能和更優秀的調試性能。硬件調試器的基本原理是通過仿真硬件的執行過程,讓開發者在調試時可以隨時了解到系統的當前執行情況。目前嵌入式系統開發中最常用到的硬件調試器是ROM Monitor、ROM Emulator、In-Circuit Emulator和In-Circuit Debugger。
采用ROM Monitor方式進行交叉調試需要在宿主機上運行調試器,在目標機上運行ROM監視器(ROM Monitor)和被調試程序,宿主機通過調試器與目標機上的ROM監視器建立通信連接,它們之間的通信遵循遠程調試協議。ROM監視器可以是一段運行在目標機ROM上的可執行程序,也可以是一個專門的硬件調試設備,它負責監控目標機上被調試程序的運行情況,能夠與宿主機端的調試器一同完成對應用程序的調試。在使用這種調試方式時,被調試程序首先通過ROM監視器下載到目標機,然后在ROM監視器的監控下完成調試,目前使用的絕大部分ROM監視器能夠完成設置斷點、單步執行、查看寄存器、修改內存空間等各項調試功能。
采用ROM Emulator方式進行交叉調試時需要使用ROM仿真器,它通常被插入到目標機上的ROM插槽中,專門用于仿真目標機上的ROM芯片。在使用這種調試方式時,被調試程序首先下載到ROM仿真器中,它等效于下載到目標機的ROM芯片上,然后在ROM仿真器中完成對目標程序的調試。ROM Emulator調試方式通過使用一個ROM仿真器,雖然避免了每次修改程序后都必須重新燒寫到目標機ROM中這一費時費力的操作,但由于ROM仿真器本身比較昂貴,功能相對來講又比較單一,因此只適應于某些特定場合。
采用In-Circuit Emulator(ICE)方式進行交叉調試時需要使用在線仿真器,它是仿照目標機上的CPU而專門設計的硬件,可以完全仿真處理器芯片的行為,并且提供了非常豐富的調試功能。在使用在線仿真器進行調試的過程中,可以按順序單步執行,也可以倒退執行,還可以實時查看所有需要的數據,從而給調試過程帶來了很多的便利。嵌入式系統應用的一個顯著特點是與現實世界中的硬件直接相關,存在各種異變和事先未知的變化,從而給微處理器的指令執行帶來各種不確定因素,這種不確定性在目前情況下只有通過在線仿真器才有可能發現,因此盡管在線仿真器的價格非常昂貴,但仍然得到了非常廣泛的應用。
采用In-Circuit Debugger(ICD)方式進行交叉調試時需要使用在線調試器。由于ICE的價格非常昂貴,并且每種CPU都需要一種與之對應的ICE,使得開發成本非常高,一個比較好的解決辦法是讓CPU直接在其內部實現調試功能,并通過在開發板上引出的調試端口,發送調試命令和接收調試信息,完成調試過程。目前Motorola公司提供的開發板上使用的是DBM調試端口,而ARM公司提供的開發板上使用的則是JTAG調試端口,使用合適的軟件工具與這些調試端口進行連接,可以獲得與ICE類似的調試效果。
軟件調試
軟件調試通常要在不同的層次上進行,有時可能需要對嵌入式操作系統的內核進行調試,而有時可能僅僅只需要調試嵌入式應用程序就可以了。在嵌入式系統的整個開發過程中,不同層次上的軟件調試需要使用不同的調試方法。
嵌入式操作系統的內核調試相對來講比較困難,這是因為在內核中不便于增加一個調試器程序,而只能通過遠程調試的方法,通過串口和操作系統內置的"調試樁"(debug stub)進行通信,共同完成調試過程。調試樁可以看成是一個調試服務器,它通過操作系統獲得一些必要的調試信息,并且負責處理宿主機發送來的調試命令。具體到嵌入式Linux系統內核,調試時可以先在Linux內核中設置一個調試樁,用作調試過程中和宿主機之間的通信服務器,然后就可以在宿主機中通過調試器的串口與調試樁進行通信,并通過調試器控制目標機上Linux內核的運行。
嵌入式應用軟件的調試可以使用本地調試和遠程調試兩種方法,相對于操作系統的調試而言,這兩種方式都比較簡單。如果采用的是本地調試,首先要將所需的調試器移植到目標系統中,然后就可以直接在目標機上運行調試器來調試應用程序了;如果采用的是遠程調試,則需要移植一個調試服務器到目標系統中,并通過它與宿主機上的調試器共同完成應用程序的調試。在嵌入式Linux系統的開發中,遠程調試時目標機上使用的調試服務器通常是gdbserver,而宿主機上使用的調試器則是gdb,兩者相互配合共同完成調試過程。
3. 系統測試
嵌入式系統的硬件一般采用專門的測試儀器進行測試,而軟件則需要有相關的測試技術和測試工具的支持,并要采用特定的測試策略。測試技術指的是軟件測試的專門途徑,以及能夠更加有效地運用這些途徑的特定方法。在嵌入式軟件測試中,常常要在基于目標機的測試和基于宿主機的測試之間做出折衷,基于目標機的測試需要消耗較多的時間和經費,而基于宿主機的測試雖然代價較小,但畢竟是在仿真環境中進行的,因此難以完全反映軟件運行時的實際情況。這兩種環境下的測試可以發現不同的軟件缺陷,關鍵是要對目標機環境和宿主機環境下的測試內容進行合理取舍。
測試工具指的是那些能夠用來輔助測試的工具,測試工具主要用來支持測試人員的測試工作,本身不能直接用來進行測試,測試工具一般都是通用工具,測試人員應該根據實際情況對它們進行適當的調整。嵌入式軟件測試中經常用到測試工具主要有內存分析工具、性能分析工具、覆蓋分析工具、缺陷跟蹤工具等。
內存分析工具
嵌入式系統的內存資源通常是受限的,內存分析工具可以用來處理在進行動態內存分配時產生的缺陷。當動態分配的內存被錯誤地引用時,產生的錯誤通常難以再現,可出現的失效難以追蹤,使用內存分析工具可以很好地檢測出這類缺陷。目前常用的內存分析工具有軟件和硬件兩種,基于軟件的內存分析工具可能會對代碼的執行性能帶來很大影響,從而影響系統的實時性;基于硬件的內存分析工具價格昂貴,并且只能在特定的環境中使用。
性能分析工具
嵌入式系統的性能通常是一個非常關鍵的因素,開發人員一般需要對系統的某些關鍵代碼進行優化來改進性能,而首先遇到的問題自然就是確定需要對哪些代碼進行優化。性能分析工具可以為開發人員提供有關的數據,說明執行時間是如何消耗的,是什么時候消耗的,以及每個進程所使用的時間。這些數據可以幫助確定哪些進程消耗了過多的執行時間,從而可以決定如何優化軟件,以獲得更好的時間性能。此外,性能分析工具還可以引導開發人員發現在系統調用中存在的錯誤以及程序結構上的缺陷。
覆蓋分析工具
在進行白盒測試時,可以使用代碼覆蓋分析工具追蹤哪些代碼被執行過,分析過程一般通過插樁來完成,插樁可以是在測試環境中嵌入硬件,也可以是在可執行代碼中加入軟件,或者是兩者的結合。開發人員通過對分析結果進行總結,可以確定哪些代碼被執行過,哪些代碼被遺漏了。目前常用的覆蓋分析工具一般都會提供有關功能覆蓋、分支覆蓋、條件覆蓋等信息。
本文討論了嵌入式Linux系統的開發與一般通用計算機軟件開發的不同點及應該注意的事項,這些都是今后在進行嵌入式Linux系統開發時必須具備的基礎知識。