什么是Uclinux?
uCLinux是一個完全符合GNU/GPL公約的項目,完全開放代碼,現由Lineo公司支持維護。英文單詞中u表示Micro,小的意思,C表示Control,控制的意思,所以uCLinux就是Micro-Control-Linux,字面上的理解就是“微控制領域中的Linux系統”。它專門針對沒有MMU的CPU,并專為嵌入式系統做了許多小型化的工作,已支持前面提到的多款CPU。官方主頁在http://www.uclinux.org。國內從事uclinux開發有合肥華恒科技等幾家公司 。
核心開發人員12人左右。To join, send mail to majordomo@uclinux.org with the command "subscribe uclinux-dev" in the body of the message.
已成功使用uCLinux的案例
合肥華恒的基于coldfire 5272/5407的家庭網關Soho/Home/VPN Router、基于68EZ328的PDA開發套件
Maple?信號處理公司基于DragonBallVZ和TMS320C541xx?DSP的DAQStick?系列嵌入式信號處理板卡
珠海萬禾的基于VZ328的多串口設備Webport2000,基于68VZ328的PDA開發套件
Lineo 公司的uCsimm、uCdimm開發套件以及商業音樂媒體服務器BMMS-MP3.COM采用
西南交通大學電氣檢測與故障診斷信息研究室的嵌入式電力設備運行狀態監測系統
NetSilicon公司 NET+Works設備網絡平臺(基于ARM7TDMI)-為Wireless Networks 公司的BlueLAN 提供接入點
東軟的智能家庭網關產品
愛立信的基于ARM7TDMI藍芽BLIP無線通信設備
基于ARM7TDMI的Aplio公司的voice-over-IP電話
AXIS公司的AXIS2001網絡數碼相機
Adomo公司的家庭機頂盒
Snapsear的VPN安全設備
瑞士洛桑的Smartdata公司的微型計算機Chipslice
uCLinux內存管理
uClinux同標準Linux的最大區別就在于內存管理????????標準Linux使用的虛擬存儲器技術
?◇標準Linux是針對有內存管理單元的處理器設計的。虛擬地址被送到內存管理單元(MMU),把虛擬地址映射為物理地址。采用分頁的方式來載入進程。實際存儲器分割為相同大小的頁面。
◇虛擬存儲器由存儲器管理機制及一個大容量的快速硬盤存儲器支持。它的實現基于局部性原理,當一個程序在運行之前,沒有必要全部裝入內存,而是僅將那些當前要運行的那些部分頁面裝入內存運行(copy-on-write),其余暫時留在硬盤上程序運行時如果它所要訪問的頁已存在,則程序繼續運行,如果發現不存在的頁,操作系統將產生一個頁失效異常,導致操作系統把需要運行的部分加載到內存中。必要時操作系統還可以把不需要的內存頁交換到磁盤上。
?◇通過賦予每個任務不同的虛擬--物理地址轉換映射(頁表),還可支持不同任務之間的保護、共享等。
?◇對于多進程管理當處理器進行進程切換并執行一個新任務時,一個重要部分就是為新任務切換頁表。
標準Linux系統的內存管理功能??
◇可以運行只加載了部分的程序,縮短了程序啟動的時間
??? ◇運行比內存還要大的程序。理想情況下應該可以運行任意大小的程序 ◇可以使多個程序同時駐留在內存中提高CPU的利用率 ◇可以運行重定位程序。即程序可以方于內存中的任何一處,而且可以在執行過程中移動 ◇寫機器無關的代碼。程序不必事先約定機器的配置情況 ◇減輕程序員分配和管理內存資源的負擔
???? ◇可以進行程序代碼共享 ◇提供內存保護,進程不能以非授權方式訪問或修改頁面,內核保護單個進程的數據和代碼以防止其它進程修改它們。否則,用戶程序可能會偶然(或惡意)的破壞內核或其它用戶程序
??? 代價:內存管理需要地址轉換表和其他一些數據結構,留給程序的內存減少了。地址轉換增加了每條指令的執行時間,而對于有額外內存操作的指令會更嚴重。當進程訪問不在內存的頁面時,系統處理失效的磁盤I/O操作極耗時間。
uCLinux針對NOMMU的特殊處理
uClinux針對沒有MMU的處理器設計,不能使用處理器的虛擬內存管理技術,但出現簡單和盡量靠攏標準Linux得需要,uClinux仍然沿用標準Linux的分頁內存管理結構,系統在啟動時把實際存儲器進行分頁,但實際上采用的是實存儲器管理策略。
uClinux系統對于內存的訪問是直接的,(它對地址的訪問不需要經過MMU,而是直接送到地址線上輸出),所有程序中訪問的地址都是實際的物理地址。
操作系統對內存空間沒有保護(這實際上是很多嵌入式系統的特點),各個進程實際上共享一個運行空間(沒有獨立的地址轉換表)。
一個進程在執行前,系統必須為進程分配足夠的連續地址空間,然后全部載入主存儲器的連續空間中。由于程序加載地址與預期(ld文件中指出的)通常都不相同,這樣relocation過程就是必須的。
磁盤交換空間無法使用的,系統執行時如果缺少內存將無法通過磁盤交換來得到改善。
uCLinux對開發人員提出的更高要求
從易用性來說,uClinux的內存管理實際上是一種倒退,退回了到了UNIX早期或是Dos系統時代。開發人員不得不參與系統的內存管理。從編譯內核開始,開發人員必須告訴系統這塊開發板到底擁有多少的內存。
由于應用程序加載時必須分配連續的地址空間,而針對可連續地址分配內存大小是受限的,開發人員在開發應用程序時必須考慮內存的分配情況并關注應用程序需要運行空間的大小。另外由于采用實存儲器管理策略,
用戶程序同內核以及其它用戶程序在一個地址空間,程序開發時要保證不侵犯其它程序的地址空間,以使得程序不至于破壞系統的正常工作,或導致其它程序的運行異常。從內存的訪問角度來看,開發人員的權利增大了(開發人員在編程時可以訪問任意的地址空間),但與此同時系統的安全性也大為下降。
從嵌入式設備實現的功能來看,嵌入式設備通常在某一特定的環境下運行,只要實現特定的功能,其功能相對簡單,內存管理的要求完全可以由開發人員考慮。
uCLinux內核加載方式
?? uCLinux的內核有兩種可選的運行方式:可以在flash上直接運行,也可以加載到內存中運行。后者可以減少內存需要。 ??? Flash運行方式(XIP):把內核的可執行映像燒寫到flash上,系統啟動時從flash的某個地址開始逐句執行。這種方法實際上是很多嵌入式系統采用的方法。 ??? 內核加載方式:把內核的壓縮文件存放在flash上,系統啟動時讀取壓縮文件在內存里解壓,然后開始執行,這種方式相對復雜一些,但是運行速度可能更快(RAM的存取速率要比Flash高)。
uCLinux根(root)文件系統
?? uCLinux系統采用romfs文件系統,這種文件系統相對于一般的ext2文件系統要求更少的空間。空間的節約來自于兩個方面:首先內核支持romfs文件系統比支持ext2文件系統需要更少的代碼;其次romfs文件系統相對簡單,在建立文件系統超級塊(superblock)需要更少的存儲空間。Romfs文件系統不支持動態擦寫保存,對于系統需要動態保存的數據采用虛擬ram盤/JFFS的方法進行處理(ram盤將采用ext2文件系統)。
uCLinux應用程序庫
uCLinux小型化的另一個做法是重寫了應用程序庫,相對于越來越大且越來越全的glibc庫,uClibc對libc做了精簡。 http://uclibc.org/uClibc.html
uClibm數學庫
uCLinux對用戶程序采用靜態鏈接的形式,這種做法會使應用程序變大,但是基于內存管理的問題,也就是基于沒有MMU的特性,只能這樣做,同時這種做法也更接近于通常嵌入式系統的做法。
標準Linux系統系統數據段,代碼段,堆和棧在虛存層面是連續的。堆向上增長,棧向下增長,在堆底和棧頂之間有256MB的內存可供分配。uClinux采用了實內存模式,各個內存段在物理內存層面是連續的,棧段在同數據段在一起,堆有系統內存管理,所有進程共享,由于內存連續和保護的要求,棧段,數據段,代碼段都是在程序加載是分配。 這種內存空間布局阻礙了動態連接庫的運用。棧段的大小固定(在生成應用時可以指定棧段大小),開發人員在開發時不得不使用一些方法估計判斷棧段的大小,使其即能滿足程序的需要,又不浪費內存。
?uClinux可執行文件格式
? uCLinux系統使用flat可執行文件格式,目前也支持elf文件格式。先解釋幾種可執行文件格式。 coff(common object file format):一種通用的對象文件格式; elf(executive linked file):一種為Linux系統所采用的通用文件格式,支持動態連接和重定位; flat:elf格式有很大的文件頭,flat文件對文件頭和一些段信息做了簡化,可執行程序小。
? 當用戶執行一個應用時,內核的執行文件加載器將對flat文件進行進一步處理,主要是對reloc段進行修正(詳見fs/binfmt_flat.c)。 需要reloc段的根本原因是,程序在連接時連接器所假定的程序運行空間與實際程序加載到的內存空間不同。假如有這樣一條指令: jsr app_start; 這一條指令采用直接尋址,跳轉到app_start地址處執行,連接程序將在編譯完成是計算出app_start的實際地址(設若實際地址為0x10000),這個實際地址是根據ld文件計算出來。但實際上由于內存分配的關系,操作系統在加載時無法保證程序將按ld文件加載。這時如果程序仍然跳轉到絕對地址0x10000處執行,通常情況這是不正確的。
?? 一個解決辦法是增加一個存儲空間,用于存儲app_start的實際地址,設若使用變量addr表示這個存儲空間。則以上這句程序將改為: movl addr, a0;??? jsr (a0); 增加的變量addr將在數據段中占用一個4字節的空間,連接器將app_start的絕對地址存儲到該變量。在可執行文件加載時,可執行文件加載器根據程序將要加載的內存空間計算出app_start在內存中的實際位置,寫入addr變量。系統在實際處理是不需要知道這個變量的確切存儲位置(也不可能知道),系統只要對整個reloc段進行處理就可以了(reloc段有標識,系統可以讀出來)。處理很簡單只需要對reloc段中存儲的值統一加上一個偏置(如果加載的空間比預想的要靠前,實際上是減去一個偏移量)。偏置由實際的物理地址起始值同ld文件指定的地址起始值相減計算出。
標準Linux 的多進程管理
??? fork創建的進程幾乎是父進程的精確復制,從fork返回后,父子進程執行同樣的程序,有同樣的數據和堆棧區,并從緊跟fork后的指令繼續執行。
???? exec系統調用提供一個進程去執行另一個進程的能力,exec系統調用是采用覆蓋舊有進程存儲器內容的方式,所以原來程序的堆棧、數據段與程序段都會被修改。 fork的優化:
??? (1)COW (寫時拷貝),首先由System V使用。不進行頁面復制,父子進程共享頁面,頁面置為只讀,無論父進程還是子進程試圖修改頁時,發生頁失效,頁失效處理程序進行頁面復制,并清除只讀標志。
??? (2)BSD采用的vfork,多數程序調用完成fork后會馬上執行exec,因此vfork不進行頁面復制,父進程將地址空間租界給子進程,并將自己阻塞,直到子進程將地址空間還給它。因此,子進程會一直使用父進程的地址空間直到它調用exec或exit,內核再將地址空間返回給父進程并喚醒它。fork非常快,甚至無需拷貝頁表。它允許一個進程使用修改另一進程的地址空間。
?? uClinux NOMMU 但支持多進程
?? MMU不是支持多進程的必要條件,只是更好的支持了多進程操作系統的實現。
?? uClinux沒有MMU管理存儲器,不支持COW的機制,因此fork 的優化只有采用vfork這一途徑,并且由于不支持虛擬地址空間,簡單復制的fork實現也必須修正reloc段。 最終,uClinux的fork/vfork都用vfork實現。子進程要么代替父進程執行(此時父進程已經sleep)直到子進程調用exit退出,要么調用exec執行一個新的進程,這個時候將產生可執行文件的加載,即使這個進程只是父進程的拷貝,這個過程也不能避免。當子進程執行exit或exec后,子進程使用wakeup把父進程喚醒,父進程繼續往下執行。
??? 經過如上各方面的小型化改造,就形成了一個高度優化的、代碼緊湊的嵌入式Linux,雖然它的體積很小,uCLinux仍然保留了Linux的大多數的優點:穩定、良好的移植性、優秀的網絡功能、完備的對各種文件系統的支持、以及標準豐富的API。它的主要特征如下: ●通用Linux API ●內核體積 < 512 KB ●內核 +文件系統<900 KB ●完整的TCP/IP 協議棧 ●支持大量其它的網絡協議 ●支持各種文件系統,包括 NFS、ext2、ROMfs and JFFS、MS-DOS和FAT16/32
?uClinux開發環境
基于uCLinux的應用開發環境一般是由目標系統硬件開發板和宿主PC機所構成。硬件開發板用于操作系統和目標系統應用軟件的運行,而操作系統內核的編譯、應用軟件的開發和調試則需要借助宿主PC機來完成。雙方之間一般通過串口建立連接關系。 建立交叉開發環境 在軟件開發環境建立方面,由于uCLinux及相關工具集都是開放源碼的項目,所以大多數軟件都可以從網絡上下載獲得。首先要在宿主機上安裝標準Linux發行版,比如Red-Hat Linux,接下來就可以建立交叉開發環境。 1.安裝交叉編譯工具 針對uCLinux目前有兩套編譯工具:m68k-coff和m68k-elf,它們都是GNU組織開發的優秀的編譯器GCC的不同應用版本。它們的區別在于形成最終flat目標碼之前的中間代碼格式分別是coff和elf類型。elf格式的編譯器比coff格式的編譯器有許多優越性,建議使用m68k-elf交叉編譯器。編譯工具包中除了交叉編譯器以外,還有鏈接器(ld)、匯編器(as)以及一些為了方便開發的二進制處理工具,包括生成靜態庫工具(ar、ranlib)、二進制碼察看工具(nm、size)、二進制格式轉換工具(objcopy)。這些都要安裝在宿主機上。
????????? 2.安裝uCLinux內核 利用已安裝的交叉編譯器編譯生成運行與目標機上的uCLinux內核。與標準Linux相同的是,uCLinux內核可以以配置的方式選擇需要安裝的模塊,而增加系統的靈活性。 3.安裝應用程序庫 用交叉編譯器編譯uC-libc和uC-libm源碼,生成libc.a應用程序庫和libm.a數學庫。 4.安裝其他工具 用GCC編譯elf2flt源碼,生成格式轉換工具elf2flt。用GCC編譯genromfs源碼,得到生成romfs工具genromfs。 經過以上的準備工作之后,下面要針對特定應用所需要的設備編寫或改造設備驅動程序。有一些設備驅動,uCLinux本身就已經具有。即便沒有,因為uCLinux開放源碼的特性,用戶也可以很方便地把自己的驅動程序加入內核。如果用戶對系統實時性,特別是硬實時有特殊的要求,uCLinux可以加入RT-Linux的實時模塊。完成這些工作,一個嵌入式應用開發平臺就已經搭建好了,在此之上,根據不同需要可以開發不同的嵌入式應用。
評論
查看更多