How Computers Boot Up.計算機的引導過程
原文標題:How Computers Boot Up
原文地址:http://duartes.org/gustavo/blog/
[註:本人水平有限,只好挑一些國外高手的精彩文章翻譯一下。一來自己復習,二來與大家分享。]
前一篇文章介紹了Intel計算機的主板與內存映射,從而為本文設定了一個系統引導階段的場景。引導(Booting)是一個復雜的,充滿技巧的,涉及多個階段,又十分有趣的過程。下圖列出了此過程的概要:
引導過程概要
當 你按下計算機的電源鍵後(現在別按!),機器就開始運轉了。一旦主板上電,它就會初始化自身的固件(firmware)——芯片組和其他零零碎碎的東西 ——並嘗試啟動CPU。如果此時出了什麽問題(比如CPU壞了或根本沒裝),那麽很可能出現的情況是電腦沒有任何動靜,除了風扇在轉。一些主板會在CPU 故障或缺失時發出鳴音提示,但以我的經驗,此時大多數機器都會處於僵死狀態。一些USB或其他設備也可能導致機器啟動時僵死。對於那些以前工作正常,突然 出現這種癥狀的電腦,一個可能的解決辦法是拔除所有不必要的設備。你也可以一次只斷開一個設備,從而發現哪個是罪魁禍首。
如果一切正常,CPU就開始運行了。在一個多處理器或多核處理器的系統中,會有一個CPU被動態的指派為引導處理器(bootstrap processor簡寫BSP),用於執行全部的BIOS和內核初始化代碼。其余的處理器,此時被稱為應用處理器(application processor簡寫AP),一直保持停機狀態直到內核明確激活他們為止。雖然Intel CPU經歷了很多年的發展,但他們一直保持著完全的向後兼容性,所以現代的CPU可以表現得跟原先1978年的Intel 8086完全一樣。其實,當CPU上電後,它就是這麽做的。在這個基本的上電過程中,處理器工作於實模式,分頁功能是無效的。此時的系統環境,就像古老的MS-DOS一樣,只有1MB內存可以尋址,任何代碼都可以讀寫任何地址的內存,這裏沒有保護或特權級的概念。
CPU上電後,大部分寄存器的都具有定義良好的初始值,包括指令指針寄存器(EIP),它記錄了下一條即將被CPU執行的指令所在的內存地址。盡管此時的Intel CPU還只能尋址1MB的內存,但憑借一個奇特的技巧,一個隱藏的基地址(其實就是個偏移量)會與EIP相加,其結果指向第一條將被執行的指令所處的地址0xFFFFFFF0(長16字節,在4GB內存空間的尾部,遠高於1MB)。這個特殊的地址叫做復位向量(reset vector),而且是現代Intel CPU的標準。
主板保證在復位向量處的指令是一個跳轉,而且是跳轉到BIOS執行入口點所在的內存映射地址。這個跳轉會順帶清除那個隱藏的、上電時的基地址。感謝芯片組提供的內存映射功能,此時的內存地址存放著CPU初始化所需的真正內容。這些內容全部是從包含有BIOS的閃存映射過來的,而此時的RAM模塊還只有隨機的垃圾數據。下面的圖例列出了相關的內存區域:
引導時的重要內存區域
隨後,CPU開始執行BIOS的代碼,初始化機器中的一些硬件。之後BIOS開始執行上電自檢過程(POST),檢測計算機中的各種組件。如果找不到一個可用的顯卡,POST就會失敗,導致BIOS進入停機狀態並發出鳴音提示(因為此時無法在屏幕上輸出提示信息)。如果顯卡正常,那麽電腦看起來就真的運轉起來了:顯示一個制造商定制的商標,開始內存自檢,天使們大聲的吹響號角。另有一些POST失敗的情況,比如缺少鍵盤,會導致停機,屏幕上顯示出錯信息。其實POST即是檢測又是初始化,還要枚舉出所有PCI設備的資源——中斷,內存範圍,I/O端口。現代的BIOS會遵循高級配置與電源接口(ACPI)協議,創建一些用於描述設備的數據表,這些表格將來會被操作系統內核用到。
POST完畢後,BIOS就準備引導操作系統了,它必須存在於某個地方:硬盤,光驅,軟盤等。BIOS搜索引導設備的實際順序是用戶可定制的。如果找不到合適的引導設備,BIOS會顯示出錯信息並停機,比如"Non-System Disk or Disk Error"沒有系統盤或驅動器故障。一個壞了的硬盤可能導致此癥狀。幸運的是,在這篇文章中,BIOS成功的找到了一個可以正常引導的驅動器。
現在,BIOS會讀取硬盤的第一個扇區(0扇區),內含512個字節。這些數據叫做主引導記錄(Master Boot Record簡稱MBR)。一般說來,它包含兩個極其重要的部分:一個是位於MBR開頭的操作系統相關的引導程序,另一個是緊跟其後的磁盤分區表。BIOS 絲毫不關心這些事情:它只是簡單的加載MBR的內容到內存地址0x7C00處,並跳轉到此處開始執行,不管MBR裏的代碼是什麽。
主引導記錄
這段在MBR內的特殊代碼可能是Windows 引導裝載程序,Linux 引導裝載程序(比如LILO或GRUB),甚至可能是病毒。與此不同,分區表則是標準化的:它是一個64字節的區塊,包含4個16字節的記錄項,描述磁盤是如何被分割的(所以你可以在一個磁盤上安裝多個操作系統或擁有多個獨立的卷)。傳統上,Microsoft的MBR代碼會查看分區表,找到一個(唯一的)標記為活動(active)的分區,加載那個分區的引導扇區(boot sector),並執行其中的代碼。引導扇區是一個分區的第一個扇區,而不是整個磁盤的第一個扇區。如果此時出了什麽問題,你可能會收到如下錯誤信息:"Invalid Partition Table"無效分區表或"Missing Operating System"操作系統缺失。這條信息不是來自BIOS的,而是由從磁盤加載的MBR程序所給出的。因此這些信息依賴於MBR的內容。
隨著時間的推移,引導裝載過程已經發展得越來越復雜,越來越靈活。Linux的引導裝載程序Lilo和GRUB可以處理很多種類的操作系統,文件系統,以及引導配置信息。他們的MBR代碼不再需要效仿上述"從活動分區來引導"的方法。但是從功能上講,這個過程大致如下:
1、 MBR本身包含有第一階段的引導裝載程序。GRUB稱之為階段一。
2、 由於MBR很小,其中的代碼僅僅用於從磁盤加載另一個含有額外的引導代碼的扇區。此扇區可能是某個分區的引導扇區,但也可能是一個被硬編碼到MBR中的扇區位置。
3、 MBR配合第2步所加載的代碼去讀取一個文件,其中包含了下一階段所需的引導程序。這在GRUB中是"階段二"引導程序,在Windows Server中是C:/NTLDR。如果第2步失敗了,在Windows中你會收到錯誤信息,比如"NTLDR is missing"NTLDR缺失。階段二的代碼進一步讀取一個引導配置文件(比如在GRUB中是grub.conf,在Windows中是boot.ini)。之後要麽給用戶顯示一些引導選項,要麽直接去引導系統。
4、 此時,引導裝載程序需要啟動操作系統核心。它必須擁有足夠的關於文件系統的信息,以便從引導分區中讀取內核。在Linux中,這意味著讀取一個名字類似"vmlinuz-2.6.22-14-server"的含有內核鏡像的文件,將之加載到內存並跳轉去執行內核引導代碼。在Windows Server 2003中,一部份內核啟動代碼是與內核鏡像本身分離的,事實上是嵌入到了NTLDR當中。在完成一些初始化工作以後,NTDLR從"c:/Windows/System32/ntoskrnl.exe"文件加載內核鏡像,就像GRUB所做的那樣,跳轉到內核的入口點去執行。
這裏還有一個復雜的地方值得一提(這也是我說引導富於技巧性的原因)。當前Linux內核的鏡像就算被壓縮了,在實模式下,也沒法塞進640KB的可用RAM裏。我的vanilla Ubuntu內核壓縮後有1.7MB。然而,引導裝載程序必須運行於實模式,以便調用BIOS代碼去讀取磁盤,所以此時內核肯定是沒法用的。解決之道是使用一種倍受推崇的"虛模式"。它並非一個真正的處理器運行模式(希望Intel的工程師允許我以此作樂),而是一個特殊技巧。程序不斷的在實模式和保護模式之間切換,以便訪問高於1MB的內存同時還能使用BIOS。如果你閱讀了GRUB的源代碼,你就會發現這些切換到處都是(看看stage2/目錄下的程序,對real_to_prot 和 prot_to_real函數的調用)。在這個棘手的過程結束時,裝載程序終於千方百計的把整個內核都塞到內存裏了,但在這後,處理器仍保持在實模式運行。
至此,我們來到了從"引導裝載"跳轉到"早期的內核初始化"的時刻,就像第一張圖中所指示的那樣。在系統做完熱身運動後,內核會展開並讓系統開始運轉。下一篇文章將帶大家一步步深入Linux內核的初始化過程,讀者還可以參考Linux Cross reference的資源。我沒辦法對Windows也這麽做,但我會把要點指出來。
參考:
http://blog.csdn.net/drshenlei/article/details/4250306
How Computers Boot Up.計算機的引導過程