無論是linux還是windows,在加電後的第一步都是先執行bios(basic input/output system)程式——不知道是不是所以的電腦系統都是如此。bios儲存在主機板上的乙個non-volatile(即非易失)儲存器,如prom,eprom,flash等。——以前的bios一般都是唯讀的,現代的系統中,允許重新整理bios程式。它的任務就是簡單的初始化和識別系統硬體裝置,如cpu,記憶體,輸入/輸出裝置,外部儲存裝置等。然後找到bootloader的位置,並載入bootloader,將pc的控制權交給bootloader,完成後面的複雜的系統初始化任務。
但是在系統啟動之前,系統如何啟動bios呢?所以系統啟動的過程,也被稱為自舉。雖然沒有「先有雞還是先有蛋」那麼複雜,但是這裡也有乙個矛盾。pc是這樣解決這個問題的。將cpu設計成加電以後,就從乙個特殊的固定的位址開始執行指令,那麼bios的位置就放在這裡,也就是儲存bios的rom的起始位址就是這個固定的位址,用以保證bios程式可以在加電時被直接執行。
這裡有兩個問題:
1. bios的儲存器位址如何決定的?
2. 現在多處理器的情況下,bios是如何執行的?
下面以intel cpu為例,簡單說明一下流程:
intel cpu的第一條語句的固定位址為0xffff fff0,然後bios的儲存器被hard-map到這個記憶體位址。這樣當cpu開始執行時,實際上執行的就是bios程式。
由於bios的儲存器不會太大,所以程式一般不會太複雜,那麼不大可能實現載入作業系統的操作,只能完成簡單的初始化工作。這時,只能借助於外部儲存器了。可是外部儲存器的讀取是依賴於檔案系統的。而bios程式既然比較簡單,那麼是不可能去支援檔案系統的,更何況有各種各樣的檔案系統,不可能去一一支援。這時,還是只能依賴於硬編碼,必須定義乙個固定的外部儲存器的位址——硬碟的第乙個扇區的512位元組——被稱為mbr(master boot record)——為什麼是512位元組呢?按照我的理解,一般情況下乙個扇區都被設定為512位元組,而硬碟操作的最小單元即為乙個扇區。雖然可以設定更大的扇區,但是作為乙個統一的程式來說,使用慣例512是乙個不錯的選擇。
bios的最後一項任務就是將mbr讀入到記憶體中,且起始位址固定為0x7c00,然後對mbr的最後兩個位元組進行驗證,必須為0x55和0xaa,以保證這512位元組為mbr。驗證通過後,則跳轉到0x7c00處開始執行。這樣mbr就開始執行。——這裡,我有兩個問題,為什麼是7c00和0x55和0xaa呢?目前沒有找到當初選擇這兩個值的解釋。我依稀記得選擇0x55,0xaa是因為這個值比較特殊,利於校驗,但是為什麼利於校驗卻不記得了。
mbr儲存了分割槽表(mbr並不存在於任何乙個分割槽中,而是處於分割槽之上),以及乙個用於裝載作業系統啟動程式的小程式。mbr首先會確定活動分割槽,然後使用bios將這個活動分割槽的啟動扇區——仍然是第乙個扇區512位元組,最後跳轉到載入該啟動扇區的記憶體位址處。這樣就將pc的控制器轉移到這個啟動扇區的程式手中(即真正的bootloader)。一般來說,這個啟動程式也要求被載入到0x7c00這個位址。可是這個位址之前已經載入了mbr,如果再載入這個啟動程式,那麼必然衝突。所以mbr實際上在開始的時候,先對自己做了relocate,將自己拷貝到另外乙個位址,然後從那個位址開始執行,這樣就避免了衝突。
下面就進入了真正的bootloader了,對於linux來說,一般就是lilo和grub,下面以最常用的grub為例。
grub的啟動分為三個階段stage1,stage1.5和stage2,這三個階段也被分為三個檔案(在某些情況下,可以沒有stage1和stage1.5)。其中stage1可以嵌入到mbr中,即mbr的頭446個位元組(後面為分割槽表64位元組,0x55和0xaa兩個校驗位元組),也可以儲存在活動分割槽的第乙個扇區512位元組,
然後由mbr來載入。所以stage1最多為512位元組,如果儲存在mbr中,則只能最大為446位元組。stage1中儲存了stage1.5的位址,並負責載入stage1.5的前512位元組。之所以stage1只能載入512位元組,是為了遵循mbr的規則。
進入stage1.5,由於只載入了前512位元組,所以stage1.5首先要負責把剩餘部分**,由自己載入到記憶體中。對於stage1.5來說,它可以識別和支援檔案系統。可以檢視/boot/grub目錄下,有多個字尾為stage1.5檔案,其字首即為支援的檔案系統,也就是說要支援乙個檔案系統,就有乙個對應的stage1.5檔案。至於載入哪個檔案,已經硬編碼在stage1中。這個檔案系統為stage2所在的檔案系統。stage2檔案是真正儲存在檔案系統中的。這樣通過對應的stage1.5檔案,就可以正確載入stage2檔案。為什麼會有stage1.5這個階段呢?主要是當stage2不連續或者需要在stage2前,對檔案系統做些特殊處理。如果沒有這樣的需求,完全可以避免stage1.5。
stage2檔案為最主要的載入**,這時由於已經stage1.5已經支援檔案系統了,所以stage2可以比較大。stage2來實現grub的各種功能,這裡就不列舉了,感興趣的同學可以自己檢視grub的手冊。stage2首先需要找到grub的配置檔案,來決定如何載入作業系統。對於grub的配置與本文的主題聯絡並不緊密,我個人也對其興趣不大。
grub不僅要複雜載入kernel,還要負責載入initial ram disk,又被成為initrd。其目的主要是為了保證乙個小體積的核心。initrd為乙個簡單的檔案系統,它包含了一些核心必要的檔案和模組。這樣,首先將initrd掛載為乙個根系統,然後kernel利用這個基本的系統,來檢測環境,載入更多的必要的模組。在完成所有的載入後,這時kernel已經完全準備就緒。那麼initrd對於kernel來說,已經不需要了。這時,kernel會將initrd從根/上解除安裝,並掛載上真正的根系統,並執行正常的啟動程式。
linux 核心 核心啟動流程
cs是 段暫存器,ip是指令指標暫存器 相當於偏移位址 儲存的是 指令的位址。cs ip共同作用生成了 位址,具體演算法是cs左移4位 ip即是 位址。例如cs 0xf000,ip 0xfff0,則 位址為0xffff0.global globl 命令 global symbol global 使得...
Linux 核心載入過程
最近在研究linux的核心載入過程,對於grub是如何引導linux的核心並啟動還是有點混亂,結合網上找的一些資料總結了一下大概流程,部分是摘抄別人的,算是比較清晰思路了。arch i386 boot bootsect.s生產引導扇區的彙編 完成後跳轉到setup.s 3.16.2核心對應x86的合...
Linux載入流程筆記
bios,啟動自我測試與 mbr 我們必須要以乙個啟動管理程式來處理核心檔案載入 load 的問題,因此這個啟動管理程式就被稱為 boot loader 了。那這個boot loader 程式安裝在 呢?就在啟動裝置的第乙個磁區 sector 內,也就是我們一直談到的 mbr master boot...