1.1 Linux內核基礎知識
在動手進行Linux內核移植之前,非常有必要對Linux內核進行一定的了解,下面從Linux內核的版本和分類說起。
1.1.1 Linux版本
Linux內核的版本號可以從源代碼的頂層目錄下的Makefile中看到,比如2.6.29.1內核的Makefile中:
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 29
EXTRAVERSION = .1
其中的“VERSION”和“PATCHLEVEL”組成主版本號,比如2.4、2.5、2.6等,穩定版本的德主版本號用偶數表示(比如2.6的內核),開發中的版本號用奇數表示(比如2.5),它是下一個穩定版本內核的前身。“SUBLEVEL”稱為次版本號,它不分奇偶,順序遞增,每隔1~2個月發布一個穩定版本。“EXTRAVERSION”稱為擴展版本號,它不分奇偶,順序遞增,每周發布幾次擴展本版號。
1.1.2 什麼是標准內核
按照資料上的習慣說法,標准內核(或稱基礎內核)就是指主要在http://www.kernel.org/維護和獲取的內核,實際上它也有平台屬性的。這些linux內核並不總是適用於所有linux支持的體系結構。實際上,這些內核版本很多時候並不是為一些流行的嵌入式linux系統開發的,也很少運行於這些嵌入式linux系統上,這個站點上的內核首先確保的是在Intel X86體系結構上可以正常運行,它是基於X86處理器的內核,如對 linux-2.4.18.tar.bz2的配置make menuconfig時就可以看到,Processor type and features--->中只有386、486、586/K5/5x86/6x86/6x86MX、Pentium-Classic、 Pentium-MMX、Pentium-Pro/Celeron/Pentium-II、Pentium-III /Celeron(Coppermine)、Pentium-4、K6/K6-II/K6-III 、Athlon/Duron/K7 、Elan 、Crusoe、Winchip-C6 、Winchip-2 、Winchip-2A/Winchip-3 、CyrixIII/C3 選項,而沒有類似Samsun 2410等其他芯片的選擇。如果需要用在其他特定的處理器平台上就需要對內核進行打補丁,形成不同的嵌入式內核。實際上,不同處理器系統的內核下載站點中提供的也往往是補丁patch而已,故原x86平台上的內核變成了基礎內核,也被稱為標准內核了。
1.1.3 Linux操作系統的分類
第一層次分類:以主要功能差異和發行組織區分(基礎linux系統/內核)。
1、標准linux
2、μClinux
無MMU支持的linux系統,運行在無MMU的CPU上。
3、Linux-RT
是最早在linux上實現硬實時支持的linux發行版本。
4、Linux/RTAI
支持硬實時的linux,於RT-linux最大的不同之處在於RTAI定義了RTHAL,它將RTAI需要在linux中修改的部分定義成一組API接口,RTAI只使用API接口與linux交互。
5、Embedix
由Lineo公司開發,基於PowerPC和x86平台開發的。
6、Blue Cat Linux
7、Hard Hat Linux
8、其他
第二層分類:以應用的嵌入式平台區分(嵌入式linux系統/內核,使上面第一類中的各種linux系統擴展為對特定目標硬件的支持,成為一種具體的嵌入式linux系統)
由於嵌入式系統的發展與linux內核的發展是不同步的,所以為了要找一個能夠運行於目標系統上的內核,需要對內核進行選擇、配置和定制。因為每一種系統都是國際上不同的內核開發小組維護的,因此選擇linux內核源碼的站點也不盡相同。
第二層分類中的linux系統/內核相對於第一層分類的標准內核來說,也可以稱為嵌入式linxu系統/內核。如應用在ARM平台上的嵌入式Linux系統通常有arm-linux(常運行在arm9平台上),μClinux(常用在arm7平台上),在標准linux基礎上擴展對其他的平台的支持往往通過安裝patch實現,如armlinux就是對linux安裝rmk補丁(如patch-2.4.18-rmk7.bz2)形成的,只有安裝了這些補丁,內核才能順利地移植到ARM Linux上。也有些是已經安裝好補丁的內核源碼包,如linux-2.4.18-rmk7.tar.bz2。
不同處理器系統的內核/內核補丁下載站點:
處理器系統 適合的內核站點 下載方式
x86 http://www.kernel.org/ ftp, http, rsync
ARM http://www.arm.linux.org.uk/developer/ ftp, rsync
PowerPC http://penguinppc.org/ ftp, http, rsync, BitKeeper
MIPS http://www.linux-mips.org/ ftp, cvs
SuperH http://linuxsh.sourceforge.net/ cvs, BitKeeper
M68K http://linux-m68k.org/ ftp, http
non-MMU CPUs http://www.uclinux.org/ ftp, http
這些站點不僅僅是linux內核站點,它們可能直接提供了針對你的目標硬件系統的linux內核版本。
1.1.4 linux內核的選擇
選擇內核版本是很困難的,應該與負責維護該內核的小組保持聯系,方法是通過訂閱一些合適的郵件列表(maillist)並查看郵件中相關的重要新聞,以及浏覽一些主要站點,可以得到該內核的最新發展動態。如針對ARM的Linux內核,可以訪問http://www.arm.linux.org.uk/ 並訂閱該網站上提供的maillist就可以了。如果覺得查閱郵箱中的郵件列表耗費太多時間,那麼至少每周訪問所關心的內核網站,並閱讀Kernel Traffic提供的過去一周中在內核郵件清單中發生的重要的摘要,網址為http://kt.zork.net/kernel-traffic 這樣就可以得到相關Linux內核的最新信息。
並不是Linux的每個版本都適合ARM-Linux的移植,可以加入其郵件列表(maillist)以獲得內核版本所支持硬件的相關信息,表中列出的資源可以幫助你找到哪些沒有列出的功能可以被你的系統支持。ARM Linux的移植,建議使用2.4.x或2.6.x版本。Linux內核補丁可以到ARM Linux的ftp(ftp://ftp.arm.linux.org.uk )下載。
1.2 Linux內核啟動過程概述
一個嵌入式 Linux 系統從軟件角度看可以分為四個部分:引導加載程序(Bootloader),Linux 內核,文件系統,應用程序。其中 Bootloader是系統啟動或復位以後執行的第一段代碼,它主要用來初始化處理器及外設,然後調用 Linux 內核。Linux 內核在完成系統的初始化之後需要掛載某個文件系統做為根文件系統(Root Filesystem)。根文件系統是 Linux 系統的核心組成部分,它可以做為Linux 系統中文件和數據的存儲區域,通常它還包括系統配置文件和運行應用軟件所需要的庫。應用程序可以說是嵌入式系統的“靈魂”,它所實現的功能通常就是設計該嵌入式系統所要達到的目標。如果沒有應用程序的支持,任何硬件上設計精良的嵌入式系統都沒有實用意義。
1.2.1 Bootloader啟動過程
Bootloader在運行過程中雖然具有初始化系統和執行用戶輸入的命令等作用,但它最根本的功能就是為了啟動 Linux 內核。
1 、Bootloader的概念和作用
Bootloader 是嵌入式系統的引導加載程序,它是系統上電後運行的第一段程序,其作用類似於 PC 機上的 BIOS。在完成對系統的初始化任務之後,它會將非易失性存儲器(通常是Flash或DOC等)中的Linux 內核拷貝到 RAM 中去,然後跳轉到內核的第一條指令處繼續執行,從而啟動 Linux 內核。由此可見,Bootloader 和 Linux 內核有著密不可分的聯系,要想清楚的了解 Linux內核的啟動過程,我們必須先得認識 Bootloader的執行過程,這樣才能對嵌入式系統的整個啟動過程有清晰的掌握。
2 、Bootloader的執行過程
不同的處理器上電或復位後執行的第一條指令地址並不相同,對於 ARM 處理器來說,該地址為 0x00000000。對於一般的嵌入式系統,通常把 Flash 等非易失性存儲器映射到這個地址處,而 Bootloader就位於該存儲器的最前端,所以系統上電或復位後執行的第一段程序便是Bootloader。而因為存儲 Bootloader的存儲器不同,Bootloader的執行過程也並不相同,下面將具體分析。
嵌入式系統中廣泛采用的非易失性存儲器通常是 Flash,而 Flash 又分為 Nor Flash 和Nand Flash 兩種。 它們之間的不同在於:Nor Flash 支持芯片內執行(XIP, eXecute In Place),這樣代碼可以在Flash上直接執行而不必拷貝到RAM中去執行。而Nand Flash並不支持XIP,所以要想執行 Nand Flash 上的代碼,必須先將其拷貝到 RAM中去,然後跳到 RAM 中去執行。
3、Bootloader的功能
實際應用中的 Bootloader根據所需功能的不同可以設計得很復雜,除完成基本的初始化系統和調用 Linux 內核等基本任務外,還可以執行很多用戶輸入的命令,比如設置 Linux 啟動參數,給 Flash 分區等;也可以設計得很簡單,只完成最基本的功能。但為了能達到啟動Linux 內核的目的,所有的 Bootloader都必須具備以下功能:
(1)、初始化 RAM
因為 Linux 內核一般都會在 RAM 中運行,所以在調用 Linux 內核之前 bootloader 必須設置和初始化 RAM,為調用 Linux內核做好准備。初始化 RAM 的任務包括設置CPU 的控制寄存器參數,以便能正常使用 RAM 以及檢測RAM 大小等。
(2)、初始化串口
串口在 Linux 的啟動過程中有著非常重要的作用,它是 Linux內核和用戶交互的方式之一。Linux 在啟動過程中可以將信息通過串口輸出,這樣便可清楚的了解 Linux 的啟動過程。雖然它並不是 Bootloader 必須要完成的工作,但是通過串口輸出信息是調試Bootloader 和Linux 內核的強有力的工具,所以一般的 Bootloader 都會在執行過程中初始化一個串口做為調試端口。
(3)、檢測處理器類型
Bootloader在調用 Linux內核前必須檢測系統的處理器類型,並將其保存到某個常量中提供給 Linux 內核。Linux 內核在啟動過程中會根據該處理器類型調用相應的初始化程序。
(4)、設置 Linux啟動參數
Bootloader 在執行過程中必須設置和初始化 Linux 的內核啟動參數。目前傳遞啟動參數主要采用兩種方式:即通過 struct param_struct 和struct tag(標記列表,tagged list)兩種結構傳遞。struct param_struct ��一種比較老的參數傳遞方式,在 2.4 版本以前的內核中使用較多。從 2.4 版本以後 Linux 內核基本上采用標記列表的方式。但為了保持和以前版本的兼容性,它仍支持 struct param_struct 參數傳遞方式,只不過在內核啟動過程中它將被轉換成標記列表方式。標記列表方式是種比較新的參數傳遞方式,它必須以 ATAG_CORE 開始,並以ATAG_NONE 結尾。中間可以根據需要加入其他列表。Linux內核在啟動過程中會根據該啟動參數進行相應的初始化工作。
(5)、調用 Linux內核映像
Bootloader 完成的最後一項工作便是調用 Linux內核。如果 Linux 內核存放在 Flash 中,並且可直接在上面運行(這裡的 Flash 指 Nor Flash),那麼可直接跳轉到內核中去執行。但由於在 Flash 中執行代碼會有種種限制,而且速度也遠不及 RAM 快,所以一般的嵌入式系統都是將 Linux內核拷貝到 RAM 中,然後跳轉到 RAM 中去執行。
不論哪種情況,在跳到 Linux 內核執行之前 CPU的寄存器必須滿足以下條件:r0=0,r1=處理器類型,r2=標記列表在 RAM中的地址。