學(xué)習(xí)嵌入式linux的一點(diǎn)總結(jié).
一個嵌入式 Linux 系統(tǒng)從軟件角度看可以分為四個部分:引導(dǎo)加載程序(Bootloader), Linux 內(nèi)核,文件系統(tǒng),應(yīng)用程序。
當(dāng)系統(tǒng)首次引導(dǎo)時,或系統(tǒng)被重置時,處理器會執(zhí)行一個位于Flash/ROM中的已知位置處的代碼,Bootloader就是這第一段代碼。它主要用來初始化處理器及外設(shè),然后調(diào)用 Linux 內(nèi)核。Linux 內(nèi)核在完成系統(tǒng)的初始化之后需要掛載某個文件系統(tǒng)作為根文件系統(tǒng)(Root Filesystem),然后加載必要的內(nèi)核模塊,啟動應(yīng)用程序。這就是嵌入式Linux系統(tǒng)啟動過程 Linux 引導(dǎo)的整個過程。
根文件系統(tǒng)是 Linux 系統(tǒng)的核心組成部分,它可以作為Linux 系統(tǒng)中文件和數(shù)據(jù)的存儲區(qū)域,通常它還包括系統(tǒng)配置文件和運(yùn)行應(yīng)用軟件所需要的庫。應(yīng)用程序可以說是嵌入式系統(tǒng)的“靈魂”,它所實(shí)現(xiàn)的功能通常就是設(shè)計(jì)該嵌入式系統(tǒng)所要達(dá)到的目標(biāo)。如果沒有應(yīng)用程序的支持,任何硬件上設(shè)計(jì)精良的嵌入式系統(tǒng)都沒有實(shí)用意義。
從以上分析可以看出 Bootloader在運(yùn)行過程中雖然具有初始化系統(tǒng)和執(zhí)行用戶輸入的命令等作用,但它最根本的功能就是為了啟動 Linux 內(nèi)核,讓我們進(jìn)一步分析 Bootloader 和 Linux 內(nèi)核在嵌入式系統(tǒng)中的關(guān)系和作用。
Bootloader
1、Bootloader基本概述
Bootloader是嵌入式系統(tǒng)的引導(dǎo)加載程序,它是系統(tǒng)上電后運(yùn)行的第一段程序,其作用類似于 PC 機(jī)上的 BIOS。Bootloader是依賴于硬件而實(shí)現(xiàn)的,特別是在嵌入式領(lǐng)域,為嵌入式系統(tǒng)建立一個通用的Bootloader是很困難的,但為了能達(dá)到啟動Linux 內(nèi)核的目的,所有的 Bootloader都必須具備以下功能:
1) 初始化 RAM
因?yàn)?Linux 內(nèi)核一般都會在 RAM 中運(yùn)行,所以在調(diào)用 Linux 內(nèi)核之前 Bootloader 必須設(shè)置和初始化 RAM,為調(diào)用 Linux內(nèi)核做好準(zhǔn)備。初始化 RAM 的任務(wù)包括設(shè)置 CPU 的控制寄存器參數(shù),以便能正常使用 RAM 以及檢測RAM 大小等。
2) 初始化串口端口
在 Linux 的啟動過程中有著非常重要的作用,它是 Linux內(nèi)核和用戶交互的方式之一。Linux 在啟動過程中可以將信息通過串口輸出,這樣便可清楚的了解 Linux 的啟動過程。雖然它并不是 Bootloader 必須要完成的工作,但是通過串口輸出信息是調(diào)試 Bootloader 和Linux 內(nèi)核的強(qiáng)有力的工具,所以一般的 Bootloader 都會在執(zhí)行過程中初始化一個串口作為調(diào)試端口。
3) 檢測處理器類型
Bootloader在調(diào)用 Linux內(nèi)核前必須檢測系統(tǒng)的處理器類型,并將其保存到某個常量中提供給 Linux 內(nèi)核。Linux 內(nèi)核在啟動過程中會根據(jù)該處理器類型調(diào)用相應(yīng)的初始化程序。
4) 設(shè)置 Linux啟動參數(shù)
Bootloader在執(zhí)行過程中必須設(shè)置和初始化 Linux 的內(nèi)核啟動參數(shù)。
5) 調(diào)用 Linux內(nèi)核映像
Bootloader完成的最后一項(xiàng)工作便是調(diào)用 Linux內(nèi)核。如果 Linux 內(nèi)核存放在 Flash 中,并且可直接在上面運(yùn)行(這里的 Flash 指 Nor Flash),那么可直接跳轉(zhuǎn)到內(nèi)核中去執(zhí)行。但由于在 Flash 中執(zhí)行代碼會有種種限制,而且速度也遠(yuǎn)不及 RAM 快,所以一般的嵌入式系統(tǒng)都是將 Linux內(nèi)核拷貝到 RAM 中,然后跳轉(zhuǎn)到 RAM 中去執(zhí)行。
2、Bootloader啟動過程
嵌入式Linux系統(tǒng)通過Bootloader引導(dǎo),一上電,就要執(zhí)行Bootloader來初始化系統(tǒng)。在完成對系統(tǒng)的初始化任務(wù)之后,它會將非易失性存儲器(通常是 Flash或 DOC 等)中的Linux 內(nèi)核拷貝到 RAM 中去,然后跳轉(zhuǎn)到內(nèi)核的第一條指令處繼續(xù)執(zhí)行,從而啟動 Linux 內(nèi)核。Bootloader 和 Linux 內(nèi)核有著密不可分的聯(lián)系。
Bootloader多數(shù)有兩個階段的啟動過程:
Stage1:
- 數(shù)字列表項(xiàng)目普通列表項(xiàng)目普通列表項(xiàng)目數(shù)字列表項(xiàng)目普通列表項(xiàng)目基本的硬件初始化
- 數(shù)字列表項(xiàng)目為加載stage2準(zhǔn)備RAM空間
- 數(shù)字列表項(xiàng)目拷貝內(nèi)核映像和文件系統(tǒng)映像到RAM中
- 數(shù)字列表項(xiàng)目設(shè)置堆棧指針sp
- 數(shù)字列表項(xiàng)目跳到stage2的入口點(diǎn)
Stage2: ? - 數(shù)字列表項(xiàng)目初始化本階段要使用到的硬件設(shè)備
- 數(shù)字列表項(xiàng)目檢測系統(tǒng)的內(nèi)存映射
- 數(shù)字列表項(xiàng)目加載內(nèi)核映像和文件系統(tǒng)映像
- 數(shù)字列表項(xiàng)目設(shè)置內(nèi)核的啟動參數(shù)
嵌入式系統(tǒng)中廣泛采用的非易失性存儲器通常是 Flash,而 Bootloader就位于該存儲器的最前端,所以系統(tǒng)上電或復(fù)位后執(zhí)行的第一段程序便是 Bootloader。Bootloader在flash中的存儲示意圖如下:
3、Bootloader 的啟動方式
3.1網(wǎng)絡(luò)啟動方式
這種方式的開發(fā)板不需要較大的存儲介質(zhì),跟無盤工作站有點(diǎn)類似,但是使用這種啟動方式之前,需要把Bootloader安裝到板上的EPROM或者Flash中。Bootloader通過以太網(wǎng)接口遠(yuǎn)程下載Linux內(nèi)核映像或者文件系統(tǒng)。Bootloader下載文件一般都使用TFTP網(wǎng)絡(luò)協(xié)議,還可以通過DHCP的方式動態(tài)配置IP地址。
3.2硬盤啟動方式
傳統(tǒng)的Linux系統(tǒng)運(yùn)行在臺式機(jī)或者服務(wù)器上,這些計(jì)算機(jī)一般都使用BIOS引導(dǎo),并使用磁盤作為存儲介質(zhì)。Linux傳統(tǒng)上是LILO (Linux Loader) 引導(dǎo),后來又出現(xiàn)了GUN的軟件 (Grand Unified Bootloader) 。 這兩種Bootloader廣泛應(yīng)用在X86的Linux系統(tǒng)上。
3.3 Flash啟動方式
大多數(shù)嵌入式系統(tǒng)上都使用Flash存儲介質(zhì)。Flash有很多類型,包括NOR Flash、NAND Flash和其它半導(dǎo)體盤。它們之間的不同在于: NOR Flash 支持芯片內(nèi)執(zhí)行(XIP, eXecute In Place),這樣代碼可以在Flash上直接執(zhí)行而不必拷貝到RAM中去執(zhí)行。而NAND Flash并不支持XIP,所以要想執(zhí)行 NAND Flash 上的代碼,必須先將其拷貝到 RAM中去,然后跳到 RAM 中去執(zhí)行。NOR Flash 使用最為普遍。Bootloader一般放在Flash的底端或者頂端,這需要根據(jù)處理器的復(fù)位向量來進(jìn)行設(shè)置??梢耘渲贸蒑TD設(shè)備來訪問Flash分區(qū)。
4、Bootloader種類
嵌入式Linux系統(tǒng)已經(jīng)有各種各樣的Bootloader,種類劃分的方法也不是唯一的,一般可以按照它所支持處理器體系結(jié)構(gòu)不同進(jìn)行劃分,如下表:
常見嵌入式Linux的Bootloader有:Blob、Redboot、U-Boot
Linux內(nèi)核的啟動過程
Linux 內(nèi)核有兩種映像:一種是非壓縮內(nèi)核,叫 Image,另一種是它的壓縮版本,叫zImage。根據(jù)內(nèi)核映像的不同,Linux 內(nèi)核的啟動在開始階段也有所不同。ZImage 是 Image經(jīng)過壓縮形成的,所以它的大小比 Image 小。但為了能使用 zImage,必須在它的開頭加上解壓縮的代碼,將 ZImage 解壓縮之后才能執(zhí)行,因此它的執(zhí)行速度比 Image 要慢。但考慮到嵌入式系統(tǒng)的存儲空容量一般比較小,采用 zImage 可以占用較少的存儲空間,因此犧牲一點(diǎn)性能上的代價也是值得的。所以一般的嵌入式系統(tǒng)均采用壓縮內(nèi)核的方式。 在 Bootloader將 Linux 內(nèi)核映像拷貝到 RAM 以后,解壓內(nèi)核映像和初始化,完成剩余的與硬件平臺相關(guān)的初始化工作,再進(jìn)行一系列與內(nèi)核相關(guān)的初始化后,調(diào)用第一個用戶進(jìn)程-init 進(jìn)程并等待用戶進(jìn)程的執(zhí)行,這樣整個 Linux 內(nèi)核便啟動完畢。在很多情況下,我們可以調(diào)用一個簡單的 shell 腳本來啟動必需的嵌入式應(yīng)用程序。