讀詹榮開文檔摘html
BIOS 在完成硬件檢測和資源分配後,將硬盤 MBR 中的 Boot Loader 讀到系統的 RAM 中,而後將控制權交給 OS Boot Loaderlinux
Boot Loader執行全過程當中不響應任何中斷,中斷屏蔽經過寫CPU的中斷屏蔽寄存器或狀態寄存器完成,內核映象從硬盤上讀到RAM,跳轉到內核的入口點去運行ios
啓動操做系統系統在上電或復位時一般都從地址 0x00000000 處開始執行,而在這個地址處安排的一般就是系統的 Boot Loader 程序shell
boot loader 做用:初始化硬件設備、創建內存空間的映射圖,將系統的軟硬件環境帶到一個合適的狀態,爲調用操做系統內核準備環境網絡
硬件初始化:屏蔽全部的中斷,設置 CPU 的速度和時鐘頻率,RAM 初始化(包括正確地設置系統的內存控制器的功能寄存器以及各內存庫控制寄存器),經過 GPIO 來驅動 LED(or others)//boot loader 完成函數
OS加載兩種模式:local or remote host(ftp,tftp)網站
Boot Loader 調用 Linux 內核的方法是直接跳轉到內核的第一條指令處,也即直接跳轉到MEM_START+0x8000 地址處加密
boot loader 對串口的初始化設置可能會和內核對串口的初始化設置不一致//均可以設置串口初始化spa
the bellow from http://opens.itpub.net/7668319/viewspace-856199/操作系統
linux系統的啓動過程是由不少步驟組成的,可是,不管你是啓動一個標準的x86桌面計算機,仍是一個嵌入式PowerPC的目標板,大多數的流程是驚人得類似的。這篇文章,探索了linux從最初的啓動準備到用戶空間中某個程序被開啓之間的啓動過程,跟隨這個流程,你還能學到其餘許多與啓動有關的知識,例如,boot loaders,內核解壓縮,初始化內存盤,以及其餘一些linux啓動的部分。[@more@]在很早的時候,啓動一個計算機意味着去喂那些包含啓動程序的紙帶,或者經過手工使用前面板那密密麻麻的地址/數據/控制開關來加載啓動程序,可是,簡化這個流程並不是必須的。
讓咱們首先從一個較高的高度上來對linux的啓動作一個全面的分析,而後,咱們會回顧一下,在每個獨立的過程當中,發生了什麼事情。在這途中的參考源代碼將幫助你在內核樹中不至於迷失方向,並能繼續深刻挖掘下去。
1、 概述 圖1將是對啓動過程的總體回顧:
當系統一開始被啓動,或者從新啓動時,處理器將在衆所周知的位置執行代碼。在我的電腦上,這個位置處於基本輸入輸出系統中,也就是咱們所說的BIOS,它是被存儲在主板上的閃存中的。在嵌入式系統中,中央處理器(CPU)則將復位區域激活,來開始執行flash或者ROM中的已知的程序。在其它狀況中,基本的過程是同樣的。因爲我的電腦提供了衆多靈活的可選設備,BIOS必須肯定,由哪個設備來執行啓動過程。在接下來的文章中咱們將涉及這方面的更多的內容。
當找到啓動設備時,第一階段所用的boot loader被裝載到RAM中並被執行。這裏的boot loader在大小上小於一個扇區的大小,也就是512字節,而它的任務,就是加載第二階段的boot loader。
當負責第二階段的boot loader位於內存中並被執行時,一般會顯示一個一閃而過的屏幕,而後linux以及可選的初始化內存盤(一種臨時的根文件系統,若是想獲得具體的介紹,請訪問http://likunarmstrong.bokee.com/5502266.html)會被裝載到存儲器中。當系統鏡像被加載時,第二階段的boot loader將把控制權轉交給內核鏡像,與此同時,內核開始自解壓並初始化。在這個階段,第二階段的boot loader會檢查系統的硬件,枚舉那些附加的硬件設備,掛載根設備,以後加載須要的內核模塊。完成以後,第一個用戶空間程序(init)開始執行,更高層次的系統初始化開始。
這就是從表面上看,linux的啓動過程。好了,如今,讓咱們更進一步,更深刻地探索linux啓動過程當中的一些細節。
2、 系統的啓動
系統啓動的階段,依賴於linux在哪一個硬件設備上啓動。在嵌入式系統中,當系統被打開或者從新啓動的時候,就要使用啓動加載的環境。這方面的例子包括U-BOOT,RedBoot,和Lucent推出的MicroMonitor。嵌入式平臺一般是綁定了啓動監視器的。這些程序位於目標硬件上flash存儲器的特定位置,提供了將linux內核鏡像下載到flash存儲器的方法,並在接下來的過程當中執行它。除了擁有存儲和啓動linux鏡像的功能外,這些啓動監視器還能進行必定程度上的系統檢測和硬件初始化。在一個嵌入式的目標板中,這些啓動監視器一般覆蓋了第一階段與第二階段boot loader的功能。
/************************************************************************************************/
小知識:如何查看你的MBR內容。若是你但願查看你MBR的具體內容,請用如下命令:
# dd if=/dev/hda of=mbr.bin bs=512 count=1
# od -xa mbr.bin
須要以root身份運行的dd命令,讀取你的第一個集成電子驅動器或者IDE驅動器的前512字節,並將他們寫入
mbr.bim文件。od命令則是以十六進制和ASCII碼形式打印出這個二進制文件
/************************************************************************************************/
在我的電腦中,linux的啓動是從0xFFFF0地址開始的。BIOS的第一步動做就是進行上電自檢(POST)。POST的工做是檢查硬件設備。BIOS的第二步動做就是枚舉本地設備並初始化。
因爲BIOS功能使用上的不一樣,它由兩個部分組成:POST碼runtime服務。POST完成後,它將從存儲器中被清除,可是BIOS runtime服務會被保留,用於目標操做系統。
爲了啓動操做系統,BIOS的runtime服務將搜索那些激活狀態的或是可引導啓動的設備,搜索的順序則由CMOS設置決定(也就是咱們平時所謂的在BIOS中設置的啓動順序)。一個軟驅,一臺光驅,一個硬盤上的分區,網絡上的設備甚至一個usb 閃存盤均可以做爲一個啓動設備。
固然,linux一般是從硬盤啓動的。硬盤上的MBR(主啓動記錄)包含有基本的boot loader,它是一個512字節大小的扇區,位於磁盤的第一個扇區(0磁頭0磁道1扇區)。當MBR被裝載到RAM中後,BIOS就會將控制權轉交給MBR。
3、 第一階段boot loader
位於MBR中的主boot loader是一個512字節的鏡像,其中不只包含了程序代碼,還包含了一個小的分區表,如圖2所示。最初的446字節是主boot loader,它裏面就包含有可執行代碼以及錯誤消息文本。接下來的64字節是分區表,其中包含有四個分區的各自的記錄(一個分區佔16字節)。MBR經過特殊數字0xAA55(譯者注:在電子界中AA55確實是具備傳奇色彩的數字,想知道爲何麼?將它展開成二進制形式,看看有什麼規律)做爲兩個字節的結束標誌。0x55AA同時也是MBR有效的校驗確認。
主boot loader的工做是尋找並加載第二boot loader。它經過分析分區表,找出激活分區來完成這個任務,當它找到一個激活分區時,它將繼續掃描剩下的分區表中的分區,以便確認他們都是未激活的。確認完畢後,激活分區的啓動記錄從設備中被讀到RAM,並被執行。
4、 第二階段boot loader
起着次做用,或者說是第二boot loader,能夠更加形象得被稱爲內核加載程序。這個階段的任務就是加載linux內核,以及可選的初始化內存盤。
/*******************************************************************/
小知識:GRUB階段的boot loaders
在/boot/grub目錄中包含有stage1,stage2和stage1.5的boot loaders,同時還有很多可選的loaders(例如,CD-ROM使用的就是iso9660_stage_1_5)
/*******************************************************************/
把第一階段和第二階段的boot loaders聯合起來,就是在x86我的電腦中,咱們所說的linux loader(LILO)或者GRand Unified Bootloader(GRUB)。因爲GRUB修正了一些LILO中存在的缺陷,所以下面就讓咱們來看看GRUB(若是你但願獲得更多的關於GRUB,LILO和與之相關話題的討論資源,請見文後的參考資料)
對於GRUB來講,一個比較好的方面就是它包含了linux文件系統的知識。與LILO使用裸扇區不一樣的是,GRUB可以從ext2或者ext3文件系統中加載linux內核。它是經過將原本兩階段的boot loader轉換成三個階段的boot loader。在第一階段(MBR)中會啓動stage1.5的boot loader來理解linux內核鏡像中的特殊的文件系統格式,例如,reiserfs_stage1-5(用於從reiserf日誌文件系統中進行加載)或e2fs+stage1_5(用於從wxt2或ext3文件系統進行加載)。當stage1.5的boot loader被加載並運行時,stage2 的boot loader才能被加載。
當stage2被加載時,GRUB能根據請求的狀況顯示一個可選內核的清單(在 /etc/grub.conf 中進行定義,同時還有幾個軟符號連接 /etc/grub/menu.lst 和 /etc/grub.conf)。你能夠選擇一個內核,修改其附加的內核參數。同時,你能夠選擇使用命令行的shell來對啓動過程進行更深層次的手工控制。
在第二階段boot loader存在與內存中後,就能夠對文件系統進行查詢了,同時,默認的內核鏡像以及初始化內存盤鏡像也被加載到內存中。一切準備完畢以後,第二階段的boot loader就會調用內核鏡像。
5、 內核
(譯者注:在翻譯本章的時候,譯者發現IBM網站上已有譯好的文章,所以從本章開始以官方網站上的內容爲主)。當內核映像被加載到內存中,而且階段 2 的引導加載程序釋放控制權以後,內核階段就開始了。內核映像並非一個可執行的內核,而是一個壓縮過的內核映像。一般它是一個 zImage(壓縮映像,小於 512KB)或一個 bzImage(較大的壓縮映像,大於 512KB),它是提早使用 zlib 進行壓縮過的。在這個內核映像前面是一個例程,它實現少許硬件設置,並對內核映像中包含的內核進行解壓,而後將其放入高端內存中,若是有初始 RAM 磁盤映像,就會將它移動到內存中,並標明之後使用。而後該例程會調用內核,並開始啓動內核引導的過程。
當 bzImage(用於 i386 映像)被調用時,咱們從 ./arch/i386/boot/head.S 的 start 彙編例程開始執行(主要流程圖請參看圖 3)。這個例程會執行一些基本的硬件設置,並調用 ./arch/i386/boot/compressed/head.S 中的 startup_32 例程。此例程會設置一個基本的環境(堆棧等),並清除 Block Started by Symbol(BSS)。而後調用一個叫作 decompress_kernel 的 C 函數(在 ./arch/i386/boot/compressed/misc.c 中)來解壓內核。當內核被解壓到內存中以後,就能夠調用它了。這是另一個 startup_32 函數,可是這個函數在 ./arch/i386/kernel/head.S 中。
在這個新的 startup_32 函數(也稱爲清除程序或進程 0)中,會對頁表進行初始化,並啓用內存分頁功能。而後會爲任何可選的浮點單元(FPU)檢測 CPU 的類型,並將其存儲起來供之後使用。而後調用 start_kernel 函數(在 init/main.c 中),它會將您帶入與體系結構無關的 Linux 內核部分。實際上,這就是 Linux 內核的 main 函數。
/*******************************************************************/
小知識:GRUB 中的手工引導
在 GRUB 命令行中,咱們可使用 initrd 映像引導一個特定的內核,方法以下:
grub> kernel /bzImage-2.6.14.2
[Linux-bzImage, setup=0x1400, size=0x29672e]
grub> initrd /initrd-2.6.14.2.img
[Linux-initrd @ 0x5f13000, 0xcc199 bytes]
grub> boot
Uncompressing Linux... Ok, booting the kernel.
若是您不知道要引導的內核的名稱,只需使用斜線(/)而後按下 Tab 鍵便可。GRUB 會顯示內核和 initrd 映像列表。
/*******************************************************************/
經過調用 start_kernel,會調用一系列初始化函數來設置中斷,執行進一步的內存配置,並加載初始 RAM 磁盤。最後,要調用 kernel_thread(在 arch/i386/kernel/process.c 中)來啓動 init 函數,這是第一個用戶空間進程(user-space process)。最後,啓動空任務,如今調度器就能夠接管控制權了(在調用 cpu_idle 以後)。經過啓用中斷,搶佔式的調度器就能夠週期性地接管控制權,從而提供多任務處理能力。
在內核引導過程當中,初始 RAM 磁盤(initrd)是由階段 2 引導加載程序加載到內存中的,它會被複制到 RAM 中並掛載到系統上。這個 initrd 會做爲 RAM 中的臨時根文件系統使用,並容許內核在沒有掛載任何物理磁盤的狀況下完整地實現引導。因爲與外圍設備進行交互所須要的模塊多是 initrd 的一部分,所以內核能夠很是小,可是仍然須要支持大量可能的硬件配置。在內核引導以後,就能夠正式裝備根文件系統了(經過 pivot_root):此時會將 initrd 根文件系統卸載掉,並掛載真正的根文件系統。
initrd 函數讓咱們能夠建立一個小型的 Linux 內核,其中包括做爲可加載模塊編譯的驅動程序。這些可加載的模塊爲內核提供了訪問磁盤和磁盤上的文件系統的方法,併爲其餘硬件提供了驅動程序。因爲根文件系統是磁盤上的一個文件系統,所以 initrd 函數會提供一種啓動方法來得到對磁盤的訪問,並掛載真正的根文件系統。在一個沒有硬盤的嵌入式環境中,initrd 能夠是最終的根文件系統,或者也能夠經過網絡文件系統(NFS)來掛載最終的根文件系統。
6、 init的介紹與結束語
當內核被引導並進行初始化以後,內核就能夠啓動本身的第一個用戶空間應用程序了。這是第一個調用的使用標準 C 庫編譯的程序。在此以前,尚未執行任何標準的 C 應用程序。
在桌面 Linux 系統上,第一個啓動的程序一般是 /sbin/init。可是這不是必定的。不多有嵌入式系統會須要使用 init 所提供的豐富初始化功能(這是經過 /etc/inittab 進行配置的)。在不少狀況下,咱們能夠調用一個簡單的 shell 腳原本啓動必需的嵌入式應用程序。
與Linux 自己很是相似,Linux 的引導過程也很是靈活,能夠支持衆多的處理器和硬件平臺。最初,加載引導加載程序提供了一種簡單的方法,不用任何花架子就能夠引導 Linux。LILO 引導加載程序對引導能力進行了擴充,可是它卻缺乏文件系統的感知能力。最新一代的引導加載程序,例如 GRUB,容許 Linux 從一些文件系統(從 Minix 到 Reise)上進行引導。
from baidu,csdn