2021-05-12 14:32:11
Linux 開機引導和啟動過程詳解
你是否曾經對作業系統為何能夠執行應用程式而感到疑惑?那麼本文將為你揭開作業系統引導與啟動的面紗。
理解作業系統開機引導和啟動過程對於設定作業系統和解決相關啟動問題是至關重要的。該文章陳述了 GRUB2 引導裝載程式開機引導裝載核心的過程和 systemd 初始化系統執行開機啟動作業系統的過程。
事實上,作業系統的啟動分為兩個階段:引導boot和啟動startup。引導階段開始於開啟電源開關,結束於核心初始化完成和 systemd 進程成功執行。啟動階段接管了剩餘工作,直到作業系統進入可操作狀態。
總體來說,Linux 的開機引導和啟動過程是相當容易理解,下文將分節對於不同步驟進行詳細說明。
- BIOS 上電自檢(POST)
- 引導裝載程式 (GRUB2)
- 核心初始化
- 啟動 systemd,其是所有進程之父。
注意,本文以 GRUB2 和 systemd 為載體講述作業系統的開機引導和啟動過程,是因為這二者是目前主流的 linux 發行版本所使用的引導裝載程式和初始化軟體。當然另外一些過去使用的相關軟體仍然在一些 Linux 發行版本中使用。
引導過程
引導過程能以兩種方式之一初始化。其一,如果系統處於關機狀態,那麼開啟電源按鈕將開啟系統引導過程。其二,如果作業系統已經執行在一個本地使用者(該使用者可以是 root 或其他非特權使用者),那麼使用者可以藉助圖形介面或命令列介面通過程式設計方式發起一個重新啟動操作,從而觸發系統引導過程。重新啟動包括了一個關機和重新開始的操作。
BIOS 上電自檢(POST)
上電自檢過程中其實 Linux 沒有什麼也沒做,上電自檢主要由硬體的部分來完成,這對於所有作業系統都一樣。當電腦接通電源,電腦開始執行 BIOS(基本輸入輸出系統Basic I/O System)的 POST(上電自檢Power On Self Test)過程。
在 1981 年,IBM 設計的第一台個人電腦中,BIOS 被設計為用來初始化硬體元件。POST 作為 BIOS 的組成部分,用於檢驗電腦硬體基本功能是否正常。如果 POST 失敗,那麼這個電腦就不能使用,引導過程也將就此中斷。
BIOS 上電自檢確認硬體的基本功能正常,然後產生一個 BIOS 中斷 INT 13H,該中斷指向某個接入的可引導裝置的引導磁區。它所找到的包含有效的引導記錄的第一個引導磁區將被裝載到記憶體中,並且控制權也將從引導磁區轉移到此段程式碼。
引導磁區是引導載入器真正的第一階段。大多數 Linux 發行版本使用的引導載入器有三種:GRUB、GRUB2 和 LILO。GRUB2 是最新的,也是相對於其他老的同類程式使用最廣泛的。
GRUB2
GRUB2 全稱是 GRand Unified BootLoader,Version 2(第二版大一統引導裝載程式)。它是目前流行的大部分 Linux 發行版本的主要引導載入程式。GRUB2 是一個用於計算機尋找作業系統核心並載入其到記憶體的智慧程式。由於 GRUB 這個單詞比 GRUB2 更易於書寫和閱讀,在下文中,除特殊指明以外,GRUB 將代指 GRUB2。
GRUB 被設計為相容作業系統多重引導規範,它能夠用來引導不同版本的 Linux 和其他的開源作業系統;它還能鏈式載入專有作業系統的引導記錄。
GRUB 允許使用者從任何給定的 Linux 發行版本的幾個不同核心中選擇一個進行引導。這個特性使得作業系統,在因為關鍵軟體不相容或其它某些原因升級失敗時,具備引導到先前版本的核心的能力。GRUB 能夠通過檔案 /boot/grub/grub.conf
進行設定。(LCTT 譯註:此處指 GRUB1)
GRUB1 現在已經逐步被棄用,在大多數現代發行版上它已經被 GRUB2 所替換,GRUB2 是在 GRUB1 的基礎上重寫完成。基於 Red Hat 的發行版大約是在 Fedora 15 和 CentOS/RHEL 7 時升級到 GRUB2 的。GRUB2 提供了與 GRUB1 同樣的引導功能,但是 GRUB2 也是一個類似主框架(mainframe)系統上的基於命令列的前置作業系統(Pre-OS)環境,使得在預引導階段設定更為方便和易操作。GRUB2 通過 /boot/grub2/grub.cfg
進行設定。
兩個 GRUB 的最主要作用都是將核心載入到記憶體並執行。兩個版本的 GRUB 的基本工作方式一致,其主要階段也保持相同,都可分為 3 個階段。在本文將以 GRUB2 為例進行討論其工作過程。GRUB 或 GRUB2 的設定,以及 GRUB2 的命令使用均超過本文範圍,不會在文中進行介紹。
雖然 GRUB2 並未在其三個引導階段中正式使用這些階段stage名詞,但是為了討論方便,我們在本文中使用它們。
階段 1
如上文 POST(上電自檢)階段提到的,在 POST 階段結束時,BIOS 將查詢在接入的磁碟中查詢引導記錄,其通常位於 MBR(主開機記錄Master Boot Record),它載入它找到的第一個引導記錄中到記憶體中,並開始執行此程式碼。引導程式碼(及階段 1 程式碼)必須非常小,因為它必須連同分割區表放到硬碟的第一個 512 位元組的磁區中。 在傳統的常規 MBR 中,引導程式碼實際所佔用的空間大小為 446 位元組。這個階段 1 的 446 位元組的檔案通常被叫做引導映象(boot.img),其中不包含裝置的分割區資訊,分割區是一般單獨新增到引導記錄中。
由於引導記錄必須非常的小,它不可能非常智慧,且不能理解檔案系統結構。因此階段 1 的唯一功能就是定位並載入階段 1.5 的程式碼。為了完成此任務,階段 1.5 的程式碼必須位於引導記錄與裝置第一個分割區之間的位置。在載入階段 1.5 程式碼進入記憶體後,控制權將由階段 1 轉移到階段 1.5。
階段 1.5
如上所述,階段 1.5 的程式碼必須位於引導記錄與裝置第一個分割區之間的位置。該空間由於歷史上的技術原因而空閒。第一個分割區的開始位置在磁區 63 和 MBR(磁區 0)之間遺留下 62 個 512 位元組的磁區(共 31744 位元組),該區域用於儲存階段 1.5 的程式碼映象 core.img 檔案。該檔案大小為 25389 位元組,故此區域有足夠大小的空間用來儲存 core.img。
因為有更大的儲存空間用於階段 1.5,且該空間足夠容納一些通用的檔案系統驅動程式,如標準的 EXT 和其它的 Linux 檔案系統,如 FAT 和 NTFS 等。GRUB2 的 core.img 遠比更老的 GRUB1 階段 1.5 更複雜且更強大。這意味著 GRUB2 的階段 2 能夠放在標準的 EXT 檔案系統內,但是不能放在邏輯卷內。故階段 2 的檔案可以存放於 /boot
檔案系統中,一般在 /boot/grub2
目錄下。
注意 /boot
目錄必須放在一個 GRUB 所支援的檔案系統(並不是所有的檔案系統均可)。階段 1.5 的功能是開始執行存放階段 2 檔案的 /boot
檔案系統的驅動程式,並載入相關的驅動程式。
階段 2
GRUB 階段 2 所有的檔案都已存放於 /boot/grub2
目錄及其幾個子目錄之下。該階段沒有一個類似於階段 1 與階段 1.5 的映象檔案。相應地,該階段主要需要從 /boot/grub2/i386-pc
目錄下載入一些核心執行時模組。
GRUB 階段 2 的主要功能是定位和載入 Linux 核心到記憶體中,並轉移控制權到核心。核心的相關檔案位於 /boot
目錄下,這些核心檔案可以通過其檔名進行識別,其檔名均帶有字首 vmlinuz。你可以列出 /boot
目錄中的內容來檢視作業系統中當前已經安裝的核心。
GRUB2 跟 GRUB1 類似,支援從 Linux 核心選擇之一引導啟動。Red Hat 包管理器(DNF)支援保留多個核心版本,以防最新版本核心發生問題而無法啟動時,可以恢復老版本的核心。預設情況下,GRUB 提供了一個已安裝核心的預引導選單,其中包括問題診斷選單(recuse)以及恢復選單(如果設定已經設定恢復映象)。
階段 2 載入選定的核心到記憶體中,並轉移控制權到核心程式碼。
核心
核心檔案都是以一種自解壓的壓縮格式儲存以節省空間,它與一個初始化的記憶體映像和儲存裝置對映表都儲存於 /boot
目錄之下。
在選定的核心載入到記憶體中並開始執行後,在其進行任何工作之前,核心檔案首先必須從壓縮格式解壓自身。一旦核心自解壓完成,則載入 systemd 進程(其是老式 System V 系統的 init 程式的替代品),並轉移控制權到 systemd。
這就是引導過程的結束。此刻,Linux 核心和 systemd 處於執行狀態,但是由於沒有其他任何程式在執行,故其不能執行任何有關使用者的功能性任務。
啟動過程
啟動過程緊隨引導過程之後,啟動過程使 Linux 系統進入可操作狀態,並能夠執行使用者功能性任務。
systemd
systemd 是所有進程的父進程。它負責將 Linux 主機帶到一個使用者可操作狀態(可以執行功能任務)。systemd 的一些功能遠較舊式 init 程式更豐富,可以管理執行中的 Linux 主機的許多方面,包括掛載檔案系統,以及開啟和管理 Linux 主機的系統服務等。但是 systemd 的任何與系統啟動過程無關的功能均不在此文的討論範圍。
首先,systemd 掛載在 /etc/fstab
中設定的檔案系統,包括記憶體交換檔案或分割區。據此,systemd 必須能夠存取位於 /etc
目錄下的組態檔,包括它自己的。systemd 借助其組態檔 /etc/systemd/system/default.target
決定 Linux 系統應該啟動達到哪個狀態(或目標態target)。default.target
是一個真實的 target 檔案的符號連結。對於桌面系統,其連結到 graphical.target
,該檔案相當於舊式 systemV init 方式的 runlevel 5。對於一個伺服器作業系統來說,default.target
更多是預設連結到 multi-user.target
, 相當於 systemV 系統的 runlevel 3。 emergency.target
相當於單使用者模式。
(LCTT 譯註:“target” 是 systemd 新引入的概念,目前尚未發現有官方的準確譯名,考慮到其作用和使用的上下文環境,我們認為翻譯為“目標態”比較貼切。以及,“unit” 是指 systemd 中服務和目標態等各個物件/檔案,在此依照語境譯作“單元”。)
注意,所有的目標態target和服務service均是 systemd 的單元unit。
如下表 1 是 systemd 啟動的目標態target和老版 systemV init 啟動執行級別runlevel的對比。這個 systemd 目標態別名 是為了 systemd 向前相容 systemV 而提供。這個目標態別名允許系統管理員(包括我自己)用 systemV 命令(例如 init 3
)改變執行級別。當然,該 systemV 命令是被轉發到 systemd 進行解釋和執行的。
SystemV 執行級別 | systemd 目標態 | systemd 目標態別名 | 描述 |
---|---|---|---|
halt.target |
停止系統執行但不切斷電源。 | ||
0 | poweroff.target |
runlevel0.target |
停止系統執行並切斷電源. |
S | emergency.target |
單使用者模式,沒有服務進程執行,檔案系統也沒掛載。這是一個最基本的執行級別,僅在主控制台上提供一個 shell 用於使用者與系統進行互動。 | |
1 | rescue.target |
runlevel1.target |
掛載了檔案系統,僅執行了最基本的服務進程的基本系統,並在主控制台啟動了一個 shell 存取入口用於診斷。 |
2 | runlevel2.target |
多使用者,沒有掛載 NFS 檔案系統,但是所有的非圖形介面的服務進程已經執行。 | |
3 | multi-user.target |
runlevel3.target |
所有服務都已執行,但只支援命令列介面存取。 |
4 | runlevel4.target |
未使用。 | |
5 | graphical.target |
runlevel5.target |
多使用者,且支援圖形介面介面。 |
6 | reboot.target |
runlevel6.target |
重新啟動。 |
default.target |
這個目標態target是總是 multi-user.target 或 graphical.target 的一個符號連結的別名。systemd 總是通過 default.target 啟動系統。default.target 絕不應該指向 halt.target 、 poweroff.target 或 reboot.target 。 |
表 1 老版本 systemV 的 執行級別與 systemd 與目標態target或目標態別名的比較
每個目標態target有一個在其組態檔中描述的依賴集,systemd 需要首先啟動其所需依賴,這些依賴服務是 Linux 主機執行在特定的功能級別所要求的服務。當組態檔中所有的依賴服務都載入並執行後,即說明系統執行於該目標級別。
systemd 也會檢視老式的 systemV init 目錄中是否存在相關啟動檔案,若存在,則 systemd 根據這些組態檔的內容啟動對應的服務。在 Fedora 系統中,過時的網路服務就是通過該方式啟動的一個範例。
如下圖 1 是直接從 bootup 的 man 頁面拷貝而來。它展示了在 systemd 啟動過程中一般的事件序列和確保成功的啟動的基本的順序要求。
sysinit.target
和 basic.target
目標態可以被視作啟動過程中的狀態檢查點。儘管 systemd 的設計初衷是並行啟動系統服務,但是部分服務或功能目標態是其它服務或目標態的啟動的前提。系統將暫停於檢查點直到其所要求的服務和目標態都滿足為止。
sysinit.target
狀態的到達是以其所依賴的所有資源模組都正常啟動為前提的,所有其它的單元,如檔案系統掛載、交換檔案設定、裝置管理器的啟動、亂數生成器種子設定、低階別系統服務初始化、加解密服務啟動(如果一個或者多個檔案系統加密的話)等都必須完成,但是在 sysinit.target 中這些服務與模組是可以並行啟動的。
sysinit.target
啟動所有的低階別服務和系統初具功能所需的單元,這些都是進入下一階段 basic.target 的必要前提。
圖 1:systemd 的啟動流程
在 sysinit.target
的條件滿足以後,systemd 接下來啟動 basic.target
,啟動其所要求的所有單元。 basic.target
通過啟動下一目標態所需的單元而提供了更多的功能,這包括各種可執行檔案的目錄路徑、通訊 sockets,以及定時器等。
最後,使用者級目標態(multi-user.target
或 graphical.target
) 可以初始化了,應該注意的是 multi-user.target
必須在滿足圖形化目標態 graphical.target
的依賴項之前先達成。
圖 1 中,以 *
開頭的目標態是通用的啟動狀態。當到達其中的某一目標態,則說明系統已經啟動完成了。如果 multi-user.target
是預設的目標態,則成功啟動的系統將以命令列登入介面呈現於使用者。如果 graphical.target
是預設的目標態,則成功啟動的系統將以圖形登入介面呈現於使用者,介面的具體樣式將根據系統所設定的顯示管理器而定。
故障討論
最近我需要改變一台使用 GRUB2 的 Linux 電腦的預設引導核心。我發現一些 GRUB2 的命令在我的系統上不能用,也可能是我使用方法不正確。至今,我仍然不知道是何原因導致,此問題需要進一步探究。
grub2-set-default
命令沒能在組態檔 /etc/default/grub
中成功地設定預設核心索引,以至於期望的替代核心並沒有被引導啟動。故在該組態檔中我手動更改 GRUB_DEFAULT=saved
為 GRUB_DEFAULT=2
,2 是我需要引導的安裝好的核心檔案的索引。然後我執行命令 grub2-mkconfig > /boot/grub2/grub.cfg
建立了新的 GRUB 組態檔,該方法如預期的規避了問題,並成功引導了替代的核心。
結論
GRUB2、systemd 初始化系統是大多數現代 Linux 發行版引導和啟動的關鍵元件。儘管在實際中,systemd 的使用還存在一些爭議,但是 GRUB2 與 systemd 可以密切地配合先載入核心,然後啟動一個業務系統所需要的系統服務。
儘管 GRUB2 和 systemd 都比其前任要更加複雜,但是它們更加容易學習和管理。在 man 頁面有大量關於 systemd 的幫助說明,freedesktop.org 也線上收錄了完整的此幫助說明。下面有更多相關資訊連結。
附加資源
- GNU GRUB (Wikipedia)
- GNU GRUB Manual (GNU.org)
- Master Boot Record (Wikipedia)
- Multiboot specification (Wikipedia)
- systemd (Wikipedia)
- systemd bootup process (Freedesktop.org)
- systemd index of man pages (Freedesktop.org)
作者簡介:
David Both 居住在美國北卡羅納州的首府羅利,是一個 Linux 開源貢獻者。他已經從事 IT 行業 40 餘年,在 IBM 教授 OS/2 20餘年。1981 年,他在 IBM 開發了第一個關於最初的 IBM 個人電腦的培訓課程。他也曾在 Red Hat 教授 RHCE 課程,也曾供職於 MCI worldcom,Cico 以及北卡羅納州等。他已經為 Linux 開源社群工作近 20 年。
via: https://opensource.com/article/17/2/linux-boot-and-startup
作者:David Both 譯者: penghuster 校對:wxy
本文永久更新連結地址:http://www.linuxidc.com/Linux/2017-08/146494.htm
相關文章