Embedded Linux 技術(shù)與概念解析
引言
Embedded Linux技術(shù)基于開放源碼的資源,并且已經(jīng)是當(dāng)今最重要的嵌入式應(yīng)用技術(shù)之一。Embedded Linux是燒錄在目標(biāo)裝置上的系統(tǒng),1個(gè)Embedded Linux系統(tǒng)包含Linux kernel與 root filesystem 2大部分,Embedded Linux系統(tǒng)到底包含哪些組成要素構(gòu)成,本文將由概念的層面進(jìn)行解析。
本文
由于目前的目標(biāo)裝置,都必須嵌入極為復(fù)雜的功能,所以嵌入式操作系統(tǒng)(Embedded system)成為嵌入式系統(tǒng)不可或缺的要素。由于嵌入式系統(tǒng)是功能導(dǎo)向的系統(tǒng),因此必須設(shè)計(jì)、選擇或購買正確(或適合)的目標(biāo)裝置,才能開始實(shí)作并嵌入嵌入式系統(tǒng)。因此,嵌入式系統(tǒng)技術(shù)是以功能、與目標(biāo)裝置為分類的1種技術(shù)。
例如,與PDA相關(guān)的目標(biāo)裝置(即硬件)、與MP3播放器相關(guān)的目標(biāo)裝置、與3G手機(jī)相關(guān)的目標(biāo)裝置...等等;使用這些目標(biāo)裝置所開發(fā)的特定功能系統(tǒng),便是PDA的嵌入式系統(tǒng)、MP3音樂播放的嵌入式系統(tǒng)、3G手機(jī)的嵌入式系統(tǒng)。
Embedded Linux其實(shí)并不是1個(gè)操作系統(tǒng),而是代表應(yīng)用Linux系統(tǒng)于Embedded system的名詞。Embedded Linux的技術(shù)核心主軸是在研究如何將Linux系統(tǒng)嵌入至嵌入式目標(biāo)裝置里。
Embedded Linux是基于Linux系統(tǒng)的特殊應(yīng)用,當(dāng)然也要符合眾多標(biāo)準(zhǔn)才行。LSB與FHS標(biāo)準(zhǔn)是重要的2大標(biāo)準(zhǔn),跟隨標(biāo)準(zhǔn)不但可以提供系統(tǒng)間的兼容性,也可以提供我們1個(gè)Linux系統(tǒng)的建構(gòu)依據(jù)。
GNU/Linux的2個(gè)標(biāo)準(zhǔn)
由FSG (Free Standards Group) 所主持的 LSB (Linux Standard Base) 項(xiàng)目即是在制定 GNU/Linux 標(biāo)準(zhǔn)。根據(jù)LSB標(biāo)準(zhǔn)所發(fā)展的GNU/Linux系統(tǒng),才能提供應(yīng)用程序最小的可執(zhí)行環(huán)境,并且可在依循LSB標(biāo)準(zhǔn)的Linux distributions上執(zhí)行無誤。例如,我們可以在符合LSB標(biāo)準(zhǔn)的Red Hat Linux上發(fā)展應(yīng)用程序,只要自行發(fā)展的Embedded Linux系統(tǒng)符合LSB標(biāo)準(zhǔn)所訂定的規(guī)范,應(yīng)用程序就可以順利移植到Embedded Linux上執(zhí)行。
LSB標(biāo)準(zhǔn)提供我們發(fā)展Embedded Linux的依據(jù),雖然Embedded Linux系統(tǒng)是最小化的Linux,但因?yàn)镋mbedded Linux是嵌入式系統(tǒng)的軟件平臺(tái),所以我們不能任意精簡Linux系統(tǒng),在精簡的過程中仍要保留最基本的操作系統(tǒng)環(huán)境,而LSB的標(biāo)準(zhǔn)正是在制定這些基本的需求。
FHS全名為Filesystem Hierarchy Standard,是定義檔案與目錄標(biāo)準(zhǔn)的文件,F(xiàn)HS的標(biāo)準(zhǔn),定義了目錄與檔案的擺放位置,而UNIX-like的系統(tǒng)則是根據(jù)這個(gè)標(biāo)準(zhǔn),管理整個(gè)檔案結(jié)構(gòu)。因此,不管是系統(tǒng)廠商、Linux/UNIX distribution發(fā)展者、應(yīng)用程序作者、套件管理者、系統(tǒng)維護(hù)人員都應(yīng)該要依照FHS的標(biāo)準(zhǔn)來管理UNIX系統(tǒng)的目錄與檔案。
Embedded Linux的特色是大量使用自由軟件、與開放源碼軟件(FOSS- Free & Open Source Softwar)資源,任何你想要的軟件,幾乎都能在網(wǎng)絡(luò)上找到自由軟件已經(jīng)成為Embedded Linux技術(shù)的重要支柱。自由軟件資源包山包海,舉凡應(yīng)用程序、系統(tǒng)工具、網(wǎng)絡(luò)工具、鏈接庫、圖形接口、小型瀏覽器、程序發(fā)展工具...等等都能找得到。
Busybox
Busybox是重要的Embedded Linux工具箱,這個(gè)工具箱提供基本的UNIX指令、系統(tǒng)程序(daemon)與開機(jī)程序(init process)。Busybox用來建造1個(gè)基本、最小化且可開機(jī)的Linux系統(tǒng),由于Busybox里的指令與工具都經(jīng)過最小化處理,因此已經(jīng)是目前主要應(yīng)用在Embedded Linux實(shí)作上的開放源碼項(xiàng)目了。
Embedded Linux的組成
圖 Embedded Linux整體架構(gòu)
Embedded Linux平臺(tái)除了Linux kernel外,還包含共享鏈接庫(shared library)。shared libraries是Linux kernel的重要支持,并且也是Linux架構(gòu)里獨(dú)立的1層。在應(yīng)用程序方面,許多現(xiàn)存的開放源碼項(xiàng)目都可以直接移植到ARM9平臺(tái)。但這里所指的移植是對(duì)原始碼進(jìn)行跨平臺(tái)編譯(cross compile),并不是BSP(board support package)的移植。
跨平臺(tái)編譯
因?yàn)殚_放源碼開發(fā)工具的特性,在應(yīng)用程序級(jí)別的移植工具上,可以有1套比較系統(tǒng)化的方法,也有相關(guān)的工具與環(huán)境可以使用,目前最熱門的跨平臺(tái)編譯環(huán)境為OpenEmbedded。開放源碼軟件采用GNU Autoconf與GNU Automake來撰寫編譯法則(Makefile),因此實(shí)務(wù)上,要將應(yīng)用程序移植到ARM9平臺(tái),大部分案例只需要做跨平臺(tái)編譯即可。要了解如何將原始碼移植到ARM9平臺(tái),需要學(xué)會(huì)GNU Autoconf以及GNU Automake的使用。
GNU Autoconf
Autoconf是m4宏的擴(kuò)充套件,可以用來自動(dòng)設(shè)定軟件套件的原始碼。Autoconf會(huì)產(chǎn)生1個(gè)協(xié)助程序編譯的設(shè)定文稿執(zhí)行檔(configuration script),以方便編譯原始碼前進(jìn)行系統(tǒng)檢查與設(shè)定,使用GNU Autoconf時(shí),必須安裝GNU m4套件。
GNU Automake
Automake是自動(dòng)產(chǎn)生Makefile.in的工具,需配合Autoconf使用,以產(chǎn)生可以讓GNU Make自動(dòng)編譯原始碼的”Makefile”檔案。
GNU Make
GNU Make會(huì)根據(jù)“Makefile”來自動(dòng)編譯程序,而編譯完成的程序?yàn)閳?zhí)行文件。GNU Make的重要特點(diǎn),是沒有特定程序語言限制,甚至可以應(yīng)用在非程序語言編譯的環(huán)境中,例如:系統(tǒng)維護(hù)工作與套件安裝,因此GNU Make可以說是系統(tǒng)自動(dòng)化的好工具。
GNU Make根據(jù)“Makefile”檔案里所定義的規(guī)則,執(zhí)行Unix命令,簡單的Makefile規(guī)格,可以利用編輯器手動(dòng)撰寫,但較復(fù)雜且與針對(duì)不同平臺(tái)的設(shè)定,則建議采用GNU Autoconf/GNU Automake來產(chǎn)生“Makefile”。當(dāng)我們能夠產(chǎn)生使用cross toolchain的Makefile時(shí),就可以將套件編譯成ARM9的執(zhí)行檔。
ARM 平臺(tái)的選擇與支持
嵌入式裝置的硬件選擇當(dāng)然沒有所謂的標(biāo)準(zhǔn),但若是談?wù)摰角度胧絃inux的應(yīng)用,在平臺(tái)的選擇上就會(huì)有一些考慮。最重要的考慮因素,當(dāng)然就是處理器對(duì)于操作系統(tǒng)的支持,如此一來,沒有MMU(內(nèi)存管理單元)的ARM7平臺(tái),就不在主要的選擇范圍內(nèi)。以下列出幾個(gè)目前普遍使用的ARM9應(yīng)用程序處理器(application processor):[!--empirenews.page--]
在選擇解決方案時(shí),若是決定采用Linux做為嵌入式操作系統(tǒng),首先當(dāng)然就是要確定廠商是否提供完整的BSP。不過,由于Linux是由社群所維護(hù)發(fā)展,因此,選擇目前Linux kernel內(nèi)有支持的平臺(tái),將會(huì)是較好的選擇,這也是為什么有許多大廠,主動(dòng)貢獻(xiàn)并提交BSP給kernel.org的原因。
目前在kernel社群比較活躍的ARM9廠商,或是社群主動(dòng)積極協(xié)助維護(hù)的SOC平臺(tái),像是ATMEL、Samsung與TI OMAP等,這些都是kernel.org的Linux kernel就有支持的處理器,這表示讓Linux支持這些平臺(tái)的方式也很簡單,就是到kernel.org下載官方的Linux kernel即可。
Crosstool
針對(duì)ARM9或是其它平臺(tái)的開發(fā),最重要的工具就是Cross Toolchain。Cross Toolchain的制作一直是Embedded Linux開發(fā)者的夢靨,大多數(shù)人選擇由網(wǎng)絡(luò)下載現(xiàn)成的開發(fā)工具,但經(jīng)常會(huì)遇到缺乏鏈接庫的編譯錯(cuò)誤。完整的Cross Toolchain包含1套基本的gcc cross compiler以及其它的應(yīng)用鏈接庫;Cross Toolchain是制作基本gcc cross compiler的工具,透過crosstool即可制作ARM9的基本toolchain。
Root Filesystem概念
Root filesystem的建置,即是在建立1個(gè)基本的Linux系統(tǒng)(base system),讓kernel在完成開機(jī)后,進(jìn)入user mode執(zhí)行使用者程序。Root filesystem的建置主要是以Busybox為主,并加入(移植)客制化的開放源碼(open source)與自由軟件(free software)。
因?yàn)榍度胧絃inux的root filesystem是依照需求加入套件,與桌面環(huán)境的Linux distribution不同,因此都是用從頭打造的方式做起。在建立root filesystem時(shí),鏈接庫相依 (library dependencies) 的議題是相當(dāng)重要的項(xiàng)目。當(dāng)root filesystem缺少必要的library時(shí),程序當(dāng)然無法執(zhí)行,甚至系統(tǒng)也會(huì)無法順利啟動(dòng)。分析應(yīng)用程序所需的相依鏈接庫,觀念如下:
(1)先利用Cross Toolchain的objdump指令觀察ELF格式里的「NEEDED」項(xiàng)目。
(2)必須再檢查這些library是否相依其它library。
1個(gè)基本且可開機(jī)的root filesystem,也稱做bootstrap root filesystem,1個(gè)可用的bootstrap root filesystem只需要包含busybox與libc即可。傳統(tǒng)的Embedded Linux應(yīng)用,大多是以NFS的方式來測試目標(biāo)裝置的完整root filesystem(full root filesystem)。以NFS進(jìn)行Embedded Linux開發(fā)測試,主要是針對(duì)目標(biāo)裝置的full root filesystem做立即(right now)的系統(tǒng)執(zhí)行測試(run-time),免除不斷打包image file、開機(jī)的惡夢。這是1種流行很久的Embedded Linux系統(tǒng)測試與開發(fā)方式,其概念如下:
(1)將target的完整root filesystem(例如ARM9 root filesystem)建置后,存放于host端的某個(gè)目錄下,例如/home/rootfs。
(2)為target制作1個(gè)NFS root filesystem,也就是bootstrap root filesystem+ NFS功能,并使用NFS root filesystem將目標(biāo)裝置開機(jī)。
(3)設(shè)定host端為NFS server。
(4)以NFS mount方式將host端上的root filesystem目錄mount進(jìn)來,即可在目標(biāo)裝置上執(zhí)行full root filesystem里的應(yīng)用程序。
這種方式不但簡單,而且方便,需要的基礎(chǔ)建設(shè)如下:
1.目標(biāo)裝置使用的kernel必須支持NFS。
2.制作bootstrap root filesystem時(shí),需要加入mount指令,并且開啟mount指令的NFS功能。
3.加入NFS functionality至bootstrap root filesystem。
4.設(shè)定NFS server。
制作完成的root filesystem必須做打包的動(dòng)作,將整個(gè)root filesystem包裝成1個(gè)映像檔(image file)。根據(jù)目標(biāo)裝置的不同,我們可以將映像檔包裝成ROM fs、Compress ROM fs、ext2fs或是compress RAM fs。
ROM file system
ROM file system(romfs)是1種只讀的檔案系統(tǒng),在Embedded Linux里的主要應(yīng)用為制作romfs格式的檔案系統(tǒng)映像文件。我們將root filesystem制作成romfs filesystem的image檔。開機(jī)后,整個(gè)filesystem僅能讀取。要使用romfs filesystem必須將Linux kernel里的CONFIG_ROMFS_FS功能選項(xiàng)打開。制作ROM fs映像檔所使用的工具為genromfs。
Compressed ROM file system
Compressed ROM file system(cromfs)即是壓縮過的ROM file system,其制作方式相當(dāng)簡單,只要使用gzip將ROM file system的映像檔壓縮即可。
制作ext2fs映像檔
制作ext2fs映像檔的方式有2種。1種是使用dd指令產(chǎn)生1個(gè)空白的映像檔,接著再將此映像檔以mkfs.ext2指令格式化成ext2的格式。制作好的空白映像檔再以loopback mount方式掛載到1個(gè)目錄下,再將root filesystem整個(gè)復(fù)制到此目錄下,即可完成ext2fs映像檔的制作。
另外1種建立ext2fs映像檔的方式是使用genext2fs工具,此工具的好處是,當(dāng)我們需要在root filesystem里預(yù)先建立(pre-built)裝置文件時(shí)(device file),只需要編寫1個(gè)裝置文件表格,genext2fs工具會(huì)在打包映像檔時(shí),自動(dòng)在root filesystem里建立裝置文件。
Initial RAM disk(initrd)
RAM disk是存在于內(nèi)存中的虛擬磁盤,也就是將RAM拿來當(dāng)成磁盤使用。在Embedded Linux的應(yīng)用中,我們通常會(huì)將ramdisk當(dāng)成暫存目錄來使用。例如將/dev/ram1附掛到/tmp目錄,以便能讓應(yīng)用程序存放暫時(shí)性檔案。/dev/ram?為ramdisk的device file。由于整個(gè)root filesystem是從真正的儲(chǔ)存裝置讀取并加載至ramdisk,因此有1個(gè)重要的特性是對(duì)file system所做的任何修改,都不會(huì)影響到真正root filesystem的內(nèi)容。
initrd全名為initialize RAM disk,是1個(gè)特殊的RAM disk。bootloader會(huì)將initrd載至內(nèi)存,Linux kernel則可在/dev/ram0找到initrd。initrd會(huì)在Linux kernel開機(jī)前就加載,initrd正式的用途是用來存放開機(jī)時(shí)所需要的驅(qū)動(dòng)程序(因root filesystem尚未mount進(jìn)來)。在Embedded Linux應(yīng)用上,我們會(huì)利用initrd來存放整個(gè)檔案系統(tǒng)(root filesystem),也就是將root filesystem制作成ext2或romfs格式(或其它檔案系統(tǒng))的映像文件,并在開機(jī)時(shí)由bootloader加載內(nèi)存,initrd均位于/dev/ram0。要使用RAM disk與initrd,必須將Linux kernel的CONFIG_BLK_DEV_RAM以及CONFIG_BLK_DEV_INITRD)。[!--empirenews.page--]
使用initrd做為root filesystem裝置
將initial RAM disk當(dāng)成root filesystem來使用,是在Embedded Linux應(yīng)用上是相當(dāng)常見的技巧,如果我們想將initial RAM disk當(dāng)成存放root filesystem的裝置來使用,在開機(jī)時(shí),只需要配合root=的kernel開機(jī)參數(shù)即可。
initramfs
Linus本人在Linux 2.6時(shí)代所提出的 "initramfs" ,是1種更好的 "root=" 做法。簡單來說,initramfs就是kernel 2.6 的 initrd,initramfs是屬于1種compressed ramfs(ram filesystem)的映像檔。
C鏈接庫
在C鏈接庫方面,除了標(biāo)準(zhǔn)的glibc也被廣泛應(yīng)用在嵌入式系統(tǒng)領(lǐng)域外,也有一些專門針對(duì)嵌入式系統(tǒng)應(yīng)用所發(fā)展的C鏈接庫,像是uClibc以及Diet libc。但是由于現(xiàn)在的ARM9處理器計(jì)算效能都很快,平臺(tái)也多搭載大容量NAND閃存,所以許多實(shí)作都直接使用libc來實(shí)作root filesystem。
Linux驅(qū)動(dòng)程序
由于嵌入式系統(tǒng)整體來看,除了軟件開發(fā)外,也包含硬件客制化,因此驅(qū)動(dòng)程序在嵌入式系統(tǒng)技術(shù)領(lǐng)域中,占了舉足輕重的地位。學(xué)習(xí)驅(qū)動(dòng)程序需要確實(shí)了解硬件的規(guī)格與微處理器架構(gòu),并且工程師還要能分得清楚哪些東西是接口(interfacing),也就是與硬件無關(guān)的程序(machine-independent);以及哪些是站在第一線做硬件控制的程序(machine-dependent)。各種軟件硬接口與匯流排也都要精通。
了解Linux驅(qū)動(dòng)程序的架構(gòu),是進(jìn)入嵌入式Linux領(lǐng)域的重點(diǎn)功課,因?yàn)樵S多針對(duì)ARM9平臺(tái)的驅(qū)動(dòng)程序都是參考框架、或是針對(duì)特定開發(fā)板的實(shí)作,因此必須了解Linux驅(qū)動(dòng)程序的架構(gòu),并進(jìn)行修改,以符合自己的開發(fā)板與外圍規(guī)格。
Linux驅(qū)動(dòng)程序,采取嚴(yán)謹(jǐn)?shù)姆謱邮郊軜?gòu)設(shè)計(jì)(layered architecture),利用分層的架構(gòu)設(shè)計(jì)來徹底區(qū)分generic device driver(machine independent)與machine dependent driver。
Linux驅(qū)動(dòng)程序透過注冊與回呼的機(jī)制來清楚區(qū)分每1層的關(guān)系。分層架構(gòu)的實(shí)作必須在下層將自己注冊給上層,上層再回呼下層;上層的驅(qū)動(dòng)程序必須提供注冊函數(shù)供下層呼叫,下層驅(qū)動(dòng)程序所使用的注冊函數(shù)也將決定自己的上層架構(gòu)。
與user application如何互動(dòng),是撰寫驅(qū)動(dòng)程序時(shí)所要考慮的重要一環(huán),因此撰寫驅(qū)動(dòng)程序時(shí),要提供什么功能給應(yīng)用程序引用,就必須事先定義清楚。Linux的 generic device driver層已經(jīng)幫我們把這些功能定義清楚了。Linux驅(qū)動(dòng)程序如何透過I/O port或I/O memory來控制裝置,也就是與芯片組的溝通,方式是使用Linux kernel所提供的I/O函數(shù)來存取并控制實(shí)體硬件裝置。
Linux驅(qū)動(dòng)程序的裝置文件
Device files是UNIX系統(tǒng)的獨(dú)特觀念,在UNIX系統(tǒng)底下我們把外部的周邊裝置均視為1個(gè)檔案,并透過此檔案與實(shí)體硬件溝通,這樣的檔案就叫做device files或special files。
Device file的major number代表1個(gè)特定的裝置,例如major number 1為”null”虛擬裝置,major number定義于kernel文件目錄Documentation/devices.txt。Minor number代表裝置上的子裝置,例如同1個(gè)硬盤上的分割區(qū)就用不同的major number來代表,但其major number相同。
我們在設(shè)計(jì)device driver時(shí),會(huì)先透過1個(gè)“注冊”(register)的動(dòng)作,將自己注冊到kernel里,注冊時(shí),我們會(huì)指定1個(gè)major number參數(shù),以指定此驅(qū)動(dòng)程序所要實(shí)作的外圍裝置。當(dāng)user開啟device file時(shí),kernel便會(huì)根據(jù)device file的 major number找到對(duì)應(yīng)的驅(qū)動(dòng)程序響應(yīng)使用者。Minor number則是device driver內(nèi)部所使用,kernel并不會(huì)處理不同的minor number。
Linux 2.6的kobject模型
Linux 2.6在驅(qū)動(dòng)程序的架構(gòu)方面,加入kobject的概念。kobject以更有系統(tǒng)、組織的方式維護(hù)系統(tǒng)里的driver(集中式管理),但并非改變現(xiàn)有(kernel 2.4以來)的driver架構(gòu)。在kobject的模型下,可以看到1個(gè)platform driver觀念。所謂「platform driver」就是machine- dependent driver,當(dāng)驅(qū)動(dòng)程序設(shè)計(jì)師在kernel 2.6底下實(shí)作machine-dependent driver時(shí),就要以platform driver的架構(gòu)來實(shí)作。例如,針對(duì)我們的目標(biāo)裝置進(jìn)行硬件層的驅(qū)動(dòng)程序撰寫時(shí),就要以platform driver的方式來撰寫,實(shí)作上,只是多1個(gè)注冊到platform driver層的動(dòng)作而已。
Flash裝置的支持
針對(duì)嵌入式系統(tǒng)經(jīng)常使用的閃存(Flash)儲(chǔ)存裝置,Linux kernel支持JFFS2與NFTL 2個(gè)專門針對(duì)快閃記億體設(shè)計(jì)的檔案系統(tǒng)。JFFS2(Journaling Flash File System version 2)是專門針對(duì) NOR 型閃存所設(shè)計(jì)的檔案系統(tǒng)。NFTL(NAND Flash Translation Layer)則是專門針對(duì)NAND型閃存設(shè)計(jì)的檔案系統(tǒng)。
結(jié)論
綜合而言,Embedded Linux是1個(gè)平臺(tái)、也是一些工具的集合、也是1個(gè)嵌入式軟件的開發(fā)環(huán)境;實(shí)作上,Embedded Linux除了會(huì)進(jìn)行kernel的修改、驅(qū)動(dòng)程序的移植或開發(fā)外,也會(huì)是系統(tǒng)管理與系統(tǒng)整合的再應(yīng)用,這是一門集大成的技術(shù),并不只是1個(gè)嵌入式操作系統(tǒng),也不只是1套開發(fā)工具。