簡介 Linux是一種很受歡迎的操作系統,它與UNIX系統兼容,開放源代碼。它原本被設計為桌面系統,現在廣泛應用於服務器領域。而更大的影響在於它正逐漸的應用於嵌入式設備。UClinux正是在這種氛圍下產生的。在uClinux這個英文單詞中u表示Micro,小的意思,C表示Control,控制的意思,所以uClinux就是Micro-Control-Linux,字面上的理解就是"針對微控制領域而設計的Linux系統"。 uClinux小型化的做法 標准Linux可能采用的小型化方法 1. 重新編譯內核 Linux內核采用模塊化的設計,即很多功能塊可以獨立的加上或卸下,開發人員在設計內核時把這些內核模塊作為可選的選項,可以在編譯系統內核時指定。因此一種較通用的做法是對Linux內核重新編譯,在編譯時仔細的選擇嵌入式設備所需要的功能支持模塊,同時刪除不需要的功能。通過對內核的重新配置,可以使系統運行所需要的內核顯著減小,從而縮減資源使用量。 2. 制作root文件系統映象 Linux系統在啟動時必須加載根(root)文件系統,因此剪裁系統同時包括root file system的剪裁。在x86系統下,Linux可以在Dos下,使用Loadlin文件加載啟動, uClinux采用的小型化方法 1.uClinux的內核加載方式 uClinux的內核有兩種可選的運行方式:可以在flash上直接運行,也可以加載到內存中運行。這種做法可以減少內存需要。 Flash運行方式:把內核的可執行映象燒寫到flash上,系統啟動時從flash的某個地址開始逐句執行。這種方法實際上是很多嵌入式系統采用的方法。 內核加載方式:把內核的壓縮文件存放在flash上,系統啟動時讀取壓縮文件在內存裡解壓,然後開始執行,這種方式相對復雜一些,但是運行速度可能更快(ram的存取速率要比flash高)。同時這也是標准Linux系統采用的啟動方式。 2.uClinux的根(root)文件系統 uClinux系統采用romfs文件系統,這種文件系統相對於一般的ext2文件系統要求更少的空間。空間的節約來自於兩個方面,首先內核支持romfs文件系統比支持ext2文件系統需要更少的代碼,其次romfs文件系統相對簡單,在建立文件系統超級塊(superblock)需要更少的存儲空間。Romfs文件系統不支持動態擦寫保存,對於系統需要動態保存的數據采用虛擬ram盤的方法進行處理(ram盤將采用ext2文件系統)。 3.uClinux的應用程序庫 uClinux小型化的另一個做法是重寫了應用程序庫,相對於越來越大且越來越全的glibc庫,uClibc對libc做了精簡。 uClinux對用戶程序采用靜態連接的形式,這種做法會使應用程序變大,但是基於內存管理的問題,不得不這樣做(這將在下文對uClinux內存管理展開分析時進行說明),同時這種做法也更接近於通常嵌入式系統的做法。 uClinux的開發環境
GNU開發套件 Gnu開發套件作為通用的Linux開放套件,包括一系列的開發調試工具。主要組件: Gcc:編譯器,可以做成交叉編譯的形式,即在宿主機上開發編譯目標上可運行的二進制文件。 Binutils:一些輔助工具,包括objdump(可以反編譯二進制文件),as(匯編編譯器),ld(連接器)等等。 Gdb:調試器,可使用多種交叉調試方式,gdb-bdm(背景調試工具),gdbserver(使用以太網絡調試)。
uClinux的打印終端 通常情況下,uClinux的默認終端是串口,內核在啟動時所有的信息都打印到串口終端(使用printk函數打印),同時也可以通過串口終端與系統交互。 uClinux在啟動時啟動了telnetd(遠程登錄服務),操作者可以遠程登錄上系統,從而控制系統的運行。至於是否允許遠程登錄可以通過燒寫romfs文件系統時有用戶決定是否啟動遠程登錄服務。
交叉編譯調試工具 支持一種新的處理器,必須具備一些編譯,匯編工具,使用這些工具可以形成可運行於這種處理器的二進制文件。對於內核使用的編譯工具同應用程序使用的有所不同。在解釋不同點之前,需要對gcc連接做一些說明: .ld(linkdescription)文件:ld文件是指出連接時內存映象格式的文件。 crt0.S:應用程序編譯連接時需要的啟動文件,主要是初始化應用程序棧。 pic:position independence code ,與位置無關的二進制格式文件,在程序段中必須包括reloc段,從而使的代碼加載時可以進行重新定位。 內核編譯連接時,使用ucsimm.ld文件,形成可執行文件映象,所形成的代碼段既可以使用間接尋址方式(即使用reloc段進行尋址),也可以使用絕對尋址方式。這樣可以給編譯器更多的優化空間。因為內核可能使用絕對尋址,所以內核加載到的內存地址空間必須與ld文件中給定的內存空間完全相同。 應用程序的連接與內核連接方式不同。應用程序由內核加載(可執行文件加載器將在後面討論),由於應用程序的ld文件給出的內存空間與應用程序實際被加載的內存位置可能不同,這樣在應用程序加載的過程中需要一個重新地位的過程,即對reloc段進行修正,使得程序進行間接尋址時不至於出錯。(這個問題在i386等高級處理器上方法有所不同,本文將在後面進一步分析)。 由上述討論,至少需要兩套編譯連接工具。在討論過uClinux的內存管理後本文將給出整個系統的工作流程以及系統在flash和ram中的空間分布。
可執行文件格式 先對一些名詞作一些說明: coff(common object file format):一種通用的對象文件格式 elf(excutive linked file):一種為Linux系統所采用的通用文件格式,支持動態連接 flat:elf格式有很大的文件頭,flat文件對文件頭和一些段信息做了簡化 uClinux系統使用flat可執行文件格式,gcc的編譯器不能直接形成這種文件格式,但是可以形成coff或elf格式的可執行文件,這兩種文件需要coff2flt或elf2flt工具進行格式轉化,形成flat文件。 當用戶執行一個應用時,內核的執行文件加載器將對flat文件進行進一步處理,主要是對reloc段進行修正(可執行文件加載器的詳見fs/binfmt_flat.c)。以下對reloc段進一步討論。 需要reloc段的根本原因是,程序在連接時連接器所假定的程序運行空間與實際程序加載到的內存空間不同。假如有這樣一條指令: jsr app_start; 這一條指令采用直接尋址,跳轉到app_start地址處執行,連接程序將在編譯完成是計算出app_start的實際地址(設若實際地址為0x10000),這個實際地址是根據ld文件計算出來(因為連接器假定該程序將被加載到由ld文件指明的內存空間)。但實際上由於內存分配的關系,操作系統在加載時無法保證程序將按ld文件加載。這時如果程序仍然跳轉到絕對地址0x10000處執行,通常情況這是不正確的。一個解決辦法是增加一個存儲空間,用於存儲app_start的實際地址,設若使用變量addr表示這個存儲空間。則以上這句程序將改為: movl addr, a0; jsr (a0); 增加的變量addr將在數據段中占用一個4字節的空間,連接器將app_start的絕對地址存儲到該變量。在可執行文件加載時,可執行文件加載器根據程序將要加載的內存空間計算出app_start在內存中的實際位置,寫入addr變量。系統在實際處理是不需要知道這個變量的確切存儲位置(也不可能知道),系統只要對整個reloc段進行處理就可以了(reloc段有標識,系統可以讀出來)。處理很簡單只需要對reloc段中存儲的值統一加上一個偏置(如果加載的空間比預想的要靠前,實際上是減去一個偏移量)。偏置由實際的物理地址起始值同ld文件指定的地址起始值相減計算出。 這種reloc的方式部分是由uClinux的內存分配問題引起的,這一點將在uClinux內存管理分析時說明。
針對實時性的解決方案 uClinux本身並沒有關注實時問題,它並不是為了Linux的實時性而提出的。另外有一種Linux--Rt-linux關注實時問題。Rt-linux執行管理器把普通Linux的內核當成一個任務運行,同時還管理了實時進程。而非實時進程則交給普通Linux內核處理。這種方法已經應用於很多的操作系統用於增強操作系統的實時性,包括一些商用版UNIX系統,WindowsNT等等。這種方法優點之一是實現簡單,且實時性能容易檢驗。優點之二是由於非實時進程運行於標准Linux系統,同其它Linux商用版本之間保持了很大的兼容性。優點之三是可以支持硬實時時鐘的應用。uClinux可以使用Rt-linux的patch,從而增強uClinux的實時性,使得uClinux可以應用於工業控制、進程控制等一些實時要求較高的應用。
uClinux的內存管理 應該說uClinux同標准Linux的最大區別就在於內存管理,同時也由於uClinux的內存管理引發了一些標准Linux所不會出現的問題。本文將把uClinux內存管理同標准Linux的那內存管理部分進行比較分析。
標准Linux使用的虛擬存儲器技術 標准Linux使用虛擬存儲器技術,這種技術用於提供比計算機系統中實際使用的物理內存大得多的內存空間。使用者將感覺到好像程序可以使用非常大的內存空間,從而使得編程人員在寫程序時不用考慮計算機中的物理內存的實際容量。 為了支持虛擬存儲管理器的管理,Linux系統采用分頁(paging)的方式來載入進程。所謂分頁既是把實際的存儲器分割為相同大小的段,例如每個段1024個字節,這樣1024個字節大小的段便稱為一個頁面(page)。 虛擬存儲器由存儲器管理機制及一個大容量的快速硬盤存儲器支持。它的