計算機那些事(2)——從開機到 Linux 啟動過程詳解

baochuquan發表於2019-11-25

原文連結

首先用一張圖來大致瞭解一下計算機啟動的整個過程。

計算機那些事(2)——從開機到 Linux 啟動過程詳解

上電

按下主機的電源鍵後,計算機開始啟動,主機板上電後開始初始化其韌體(firmware)。韌體是一些固化在晶片組上的程式,它會試圖去啟動 CPU。如果啟動失敗(例如 CPU 壞了或沒插好),計算機就會當機並給出錯誤提示(如某些版本的主機板韌體會發出蜂鳴警告)。這種狀態稱為“zoombie-with-fans”。

如果前一個階段未出錯,就開始加電工作,在多 CPU 或多核 CPU 情況下,某一個 CPU 會被隨機選取作為啟動 CPU(bootstrap processor,BSP)執行 BIOS 內部的程式。其餘的 CPU(application processor,AP)保持停機直到作業系統核心顯式地使用它們。

2000 年以前的計算機主機板上均使用 BIOS,如今絕大多數計算機採用的是 EFI(Mac 用的就是 EFI)或 UEFI,BIOS 正在逐步被淘汰。基於 EFI、UEFI 的開機過程與傳統的BIOS不盡相同,本文將以傳統的 BIOS,Intel CPU 為例介紹開機過程。

此時 CPU 工作模式為真實模式,該模式下地址匯流排是 20 位,定址範圍是 0x00000~0xFFFFF 的 1M 範圍。這也就解釋了為什麼 BIOS 的容量只有 1MB。

Intel CPU 用三種執行模式: 真實模式、32 位保護模式、64 位保護模式。真實模式: Intel 8086 的定址方案,為了商業連續性,相容了這古老的方案;保護模式: 採用了虛實地址轉換方案。

BIOS 啟動之初,記憶體是空的。此時 CPU 處於真實模式,記憶體的地址對映均為硬連線的裝置。記憶體對映圖如下圖所示:

計算機那些事(2)——從開機到 Linux 啟動過程詳解

重置向量

CPU 啟動後其大多數暫存器會被初始化為預定的值,包括指令暫存器(instruction pointer, EIP),它儲存著 CPU 將要執行指令的記憶體地址。此時 CPU 會有一個特殊行為,其會對 EIP 的初始值加上一個基址暫存器的值,生成一個 32 位的地址 0xFFFFFFF0。之所以稱為特殊行為,是因為真實模式下 CPU 只能定址 1MB 地址空間,而這個 32 位地址已經大於 1MB 的記憶體限制。因此,0xFFFFFFF0 也被稱為重置向量(reset vector),參考上圖 0xFFFFFFF0 處的標識。

於是,CPU 開始執行 0xFFFFFFF0 地址處的指令,該地址處是一條 JUMP 指令,這條指令清空了基址暫存器的值,並讓指令跳回到 BIOS 開始處(實體地址為 0xF0000,參考上圖 0xF0000 處的標識)以執行 BIOS。

BIOS 內部可以分成兩個區塊: code block(普通程式)、boot block(載入程式)。上電後,boot block 會先被執行,它會檢查 code block 的程式碼是否正確,如果正確,就會轉到 code block 繼續執行下去。

BIOS 初始化

0xF0000 地址實際上是 BIOS 中的 boot block 的開始處。在這個階段,會初始化部分硬體。系統的 CPU、USB 只有部分被初始化。

BIOS POST(加電自檢)

初始化完成後,CPU 跳轉到 0xA0000 地址處(參考上圖 640KB 處)進行 BIOS 加電自檢(power on self test, POST)。這個過程會檢查計算機的各項元件,如 CPU、顯示卡、記憶體、滑鼠、鍵盤等。如果找不到記憶體或者鍵盤都有可能讓BIOS停止工作並且列印一些相關的錯誤資訊,如果找不到顯示卡 BIOS 會發出蜂鳴警告(因為無法顯示畫面) 當 CPU 執行到 0xC0000 地址處(參考上圖 768KB 處),開始尋找其他裝置的 ROM,如果找到任何其他裝置的 BIOS,它們也會被執行。 下一步,顯示卡就會顯示 BIOS 介面,並進行更深入的檢查。

BIOS 記錄系統設定值

檢查完成後,BIOS 會根據自己的“系統資源表”,對系統進行進一步確認,從而確定計算機配有哪些資源或裝置。例如 BIOS 支援隨插即用,它會檢測並配置隨插即用裝置。 然後 BIOS 會遵循高階配置電源介面(Advanced Configuration Power Interface,ACPI)在記憶體中設定好一系列的資料來描述硬體資訊,以便被作業系統核心利用。

搜尋 MBR

到這一步,BIOS 開始嘗試載入作業系統。它會從硬碟,光碟機,軟碟機,網路等幾個地方依次尋找作業系統(使用者可以在 BIOS 設定中修改查詢的優先順序)。如果找不到作業系統,BIOS 會停機並給出錯誤資訊。

假設在硬碟上找到了作業系統,它會首先讀取硬碟上的大小為 512 Bytes 的 0號扇區,這個扇區被稱為 主開機記錄(master boot record,MBR),其包含三部分:

  1. 載入程式(Boot Loader)
  2. 硬碟分割槽表(Partition Table)
  3. 結束標誌字

BIOS 讀完磁碟上的 MBR 之後會把它拷貝到記憶體 0x7C00 地址處,然後 CPU 跳轉到該記憶體地址執行 MBR 裡的指令。事實上,被複制到實體記憶體的內容就是 Boot Loader。常見的 Boot Loader 有 grub、lilo、spfdisk。下圖可以幫助大家理解 MBR 的結構。

計算機那些事(2)——從開機到 Linux 啟動過程詳解

關於磁碟、分割槽表等基礎知識,可參見 計算機那些事(1)——磁碟

Boot Loader 執行

以常見的 Linux Boot Loader —— grub 為例。

Grub 載入後首先進行 記憶體盤初始化。Boot Loader 會將儲存介質中的 initrd 檔案載入到記憶體,核心啟動時會在訪問真正的根檔案系統之前先訪問記憶體中的 initrd 檔案系統。

關於 initrd
Linux 核心需要適應多種不同的硬體架構,但是將所有的硬體驅動編入核心是不切實際的,而且核心也不可能每新出一種硬體結構,就將該硬體的裝置驅動寫入核心。實際上,Linux 的核心映象僅包含了基本的硬體驅動,在系統安裝過程中檢測系統的硬體資訊,根據安裝資訊和系統硬體資訊將一部分裝置驅動寫入 initrd(bootloader initialized RAM disk。

記憶體盤初始化完畢之後, grub 會根據配置檔案 /boot/grub/grub.cfg 設定的核心映象 vmlinuz 所在的路徑,載入核心映象,並進行解壓縮操作。此時,螢幕一般會出現 “Uncompressing Linux” 的提示。當解壓縮核心完成後,螢幕一般會輸出 “OK, booting the kernel”。

核心載入至記憶體完成後,grub 將控制權轉交給核心。

核心啟動

在 Boot Loader 配置了 initrd 的情況下,核心啟動被分成了兩個階段:

  1. 執行 initrd 的檔案系統中的 init 指令碼。此階段,核心會將控制權交給 init 檔案處理。init 主要是載入各種儲存介質相關的裝置驅動。當所需的驅動程式載入完畢,就會建立一個根裝置,然後將根檔案系統 rootfs 以只讀的方式掛載。這一步完成後,釋放未使用的記憶體,並轉換到真正的根檔案系統中,進行第 2 階段的處理。
  2. 執行真正的根檔案系統中的 /sbin/init 程式,即系統的 1 號程式。此後,系統的控制權就全權交給 /sbin/init 程式了。

系統初始化

/sbin/init 程式是系統其它所有程式的父程式,當它接管了系統控制權後,它會根據 /etc/inittab 檔案來執行相應的指令碼,從而完成一系列的系統初始化操作。主要包括以下步驟:

  1. 設定執行等級。Linux 有執行等級如下:
    • 0:關機
    • 1:單使用者模式
    • 2:無網路支援的多使用者模式
    • 3:有網路支援的多使用者模式
    • 4:保留,未使用
    • 5:有網路支援、有 X-Window 支援的多使用者模式
    • 6:重新引導系統,即重啟
  2. 執行 rc.sysinit。執行等級設定完成後,Linux 系統執行的第一個使用者層檔案是 /etc/rc.d/rc.sysinit 指令碼程式,其完成的初始化操作主要包括:設定 PATH、設定網路配置/etc/sysconfig/network、啟動 swap 分割槽、設定 /proc 等。
  3. 執行不同執行級別的指令碼程式。根據執行級別的不同,系統會執行 rc0.d ~ rc6.d 中對應的指令碼,從而完成對應的初始化工作,啟動對應的服務。
  4. 執行 /etc/rc.d/rc.localrc.local 是 Linux 執行使用者進行個性化設定的指令碼。
  5. 執行 /bin/login。進入登入狀態。此時,系統已經進入到等待使用者輸入 usernamepassword 的階段。

參考

  1. How Computers Boot Up
  2. 即將換掉傳統BIOS的UEFI
  3. Linux啟動過程詳解-《別怕Linux程式設計》之八
  4. 《Linux 系統架構與目錄解析》
  5. INITRD 詳解
  6. inux中init.d資料夾的說明
  7. Linux啟動過程分析與優化,浙江大學碩士畢業論文
  8. 深入理解linux啟動過程

(完)

相關文章