天天看點

【轉載】Linux啟動過程

轉自:http://cizixs.com/2015/01/18/linux-boot-process

簡介

我們都知道:作業系統運作的代碼是在硬碟上的,最終要跑到記憶體和 CPU 上,才能被我們使用。

那從摁下電源鍵到看到系統界面,作業系統是怎麼霸占了所有的硬體資源,把自己加載到記憶體開始運作的呢? 可以想到有兩個可能性:作業系統自己實作的,或者有其他貴人幫忙。如果是作業系統自己啟動的,就有了一個“雞生蛋,蛋生雞”的問題;如果是後者的話,一定有在作業系統啟動之前就能工作的神力,把沉睡在硬碟的作業系統變到工作狀态。

事實上,Linux 系統的啟動正是上面第二種情況。幫助把 Linux 核心(Kernel)加載到記憶體的程式是 Boot Loader,下圖的箭頭表示加載關系。

Boot Loader —-> Linux Kernel

現在隻需要知道 

Boot Loader

 位于啟動盤的第一個扇區,功能是引導 Linux 系統就可以啦,至于更詳細的說明會在後面提到。那現在的問題是 

Boot Loader

 是怎麼運作起來的?而且,系統怎麼知道哪個可啟動裝置要使用呢?有時候計算機可能啟動的裝置可能有多個:網絡、硬碟、U 盤,CD 盤等。這就需要另外一個東西來做這件事,那就是 BIOS。

BIOS —-> Boot Loader

順着上面的思路,現在的問題是:BIOS 的誰啟動的?呃,這好像是個沒有止境的過程。不過幸運的是,難題就到此結束了。BIOS 是嵌在主機闆上的固件,計算機啟動時候的約定就是啟動 BIOS 開始執行。

最後總結一下 Linux 的啟動過程:

  1. 摁下電源鍵,BIOS(Basic Input/Output System)啟動初始化硬體的工作,包括螢幕和鍵盤,記憶體檢測,這個過程也被成為 POST(Power On Self Test),然後按照 CMOS RAM 中設定的啟動裝置查找順序,來尋找可啟動裝置 。注:BIOS 程式嵌在主機闆的 ROM 晶片上的。
  2. POST 過程結束後,系統的控制權從 BISO 轉交到 boot loader。Boot loader 一般存儲在系統的硬碟上(傳統的 BIOS/MBR 系統),或者 EFI 分區上(最近的 EFI 系統)。這個時候機器不能擷取外部的存儲或者網絡資訊,一些重要的值(日期、時間、其他外部值)都是從 CMOS 裡讀取。CMOS 在計算機斷電後也能工作的裝置,Boot Loader 會在後面講解。
  3. Boot Loader 選擇要啟動的作業系統,加載核心鏡像和初始化 RAM disk 到記憶體。系統的核心開始運作,直到關機為止。

BIOS

【轉載】Linux啟動過程

摁下電源鍵的時候,計算機的一些寄存器被設定初值,指令寄存器 CS:IP 指向 BIOS 的第一條指令。BIOS 掌握控制權,來執行硬體檢測的程式,BIOS 在結束自己生命之前會尋找可啟動裝置。那麼,BIOS 怎麼知道哪些裝置室可以啟動的呢?如果計算機要從一個不能啟動的設定加載系統,會發生嚴重的錯誤。啟動裝置的第一個扇區的末尾兩個位元組一定是:

0x55

 和 

0xAA

,這兩個魔法數就是區分可啟動裝置和不可啟動裝置的關鍵。使用

sudo head -c 512 /dev/sda | hd

 可以看到第一個扇區的内容,注意最後兩個字元。

BIOS 如果找不到可啟動裝置的話,就會報

No Bootable Device Error

Boot Loader

【轉載】Linux啟動過程

對于使用 BIOS/MBR 模式的系統來說,Boot Loader 位于硬碟的第一個扇區,也稱為 MBR(Master Boot Record)。MBR 隻有 512 位元組,主要工作就是檢查分區表,并找到可以啟動的分區,一旦找到啟動分區,就在該分區裡找到後面的 Boot Loader – 比如GRUB,把它加載到記憶體(RAM)。

MBR 這麼有限的位元組空間裡,主要包括了三部分的内容:

  1. bootstrap code:啟動作業系統的代碼
  2. 分區表:訓示系統盤的位置
  3. 魔法數:0x55AA
【轉載】Linux啟動過程

對于使用 EFI/UEFI 模式的系統來說,UEFI 固件讀取 Boot Manager 的資料來決定啟動哪一個 UEFI 應用,已經找到它的位置。該固件然後啟動 UEFI 應用,比如 GRUB。

現在的控制權都到了 GRUB 啟動程式的手裡,GRUB 根據你選擇的系統(多系統的情況會有界面出現讓使用者選擇,隻有一個系統的情況會直接選擇該系統),把系統的核心加載到記憶體開始運作,同時也會初始化 RAM disk 檔案系統(initramfs)到記憶體,供核心使用,并把控制權交給核心。

Linux Kernel

【轉載】Linux啟動過程

核心一般都是壓縮的,是以它的首要任務是解壓縮,然後檢查和分析系統的硬體并初始化核心裡的硬體驅動程式。核心剛加載到記憶體的時候,檔案系統還不能使用,它使用的是 Boot Loader 加載金記憶體的 initramfs。 核心被加載到記憶體後首要工作是:初始化和配置機器的記憶體、處理器、儲存設備等,核心也會啟動一些使用者态的程式。

initramfs

【轉載】Linux啟動過程

 前面提到過 boot loader 加載到記憶體的 RAM disk,也就是 initramfs,現在就詳細講一講它。initramfs 包含的一些程式和二進制檔案,會執行一系列的動作,保證 root 檔案系統 mount 到系統。這裡動作包括,為需要的檔案系統提供核心的功能,以及使用 udev(User Device) 工具來發現和加載硬碟的驅動程式。 等到 root 檔案系統找到後,它會檢查錯誤然後 mount 到系統。

mount 程式告訴作業系統某個檔案系統可以使用,并把它加載到檔案系統的某個路徑(mount point)。如果這些動作都成功的話,initramfs 就會從記憶體中清除,init 程式(位于 /sbin/init)開始執行。

/sbin/init

【轉載】Linux啟動過程

init 處理挂載(mount)工作,是整個的檔案系統正常運作的樞紐。需要注意的時,如果在通路儲存設備的時候,需要的硬體驅動,必須在 initramfs 階段都加載好。

到目前為止,核心程式準備好了所有的硬體資源,也把檔案系統都挂載好了。它運作了 /sbin/init 程式,也就是第一個系統程序(之前運作的程式都不是 OS 級别的,不在 OS 的管轄範圍),它的程序号(pid)就是 1。下面是我在自己的系統上運作 

ps aux | grep init

的結果,第二列就是程序号:

root         1  0.0  0.0  24320   864 ?        Ss   Jan15   0:00 /sbin/init
           

第一個啟動的程式當然也肩負着比較重要的責任:把系統需要其他程式都啟動起來。傳統的 System V UNIX 工作模式下,這個過程是周遊 runlevels 序列的程式腳本,來啟動或者停止預先定義的服務(service)。除了上面那個主要的任務外,init 也負責保持系統一直運作和在 shutdown 系統的清理工作,還有使用者登入和登出的工作。

登陸和使用

前面已經說過了,init 程式負責使用者的登入和登出。如果是伺服器 linux 或者其他文本模式的 linux,init 就會啟動 getty 程式來接受使用者輸入的使用者名和密碼來驗證使用者。

如果是圖形界面的 linux, 會有 display manager 的服務負責檢測顯示屏和啟動 X-server。display manager 也負責圖形界面的使用者登陸,以及啟動正确的桌面環境。

參考資料

  1. edx 上 introduction to linux 的啟動章節
  2. 阮一峰介紹計算機啟動的文章
  3. wikipedia 上相關文章

繼續閱讀