本文主要介紹了Linux系統啓動流程相關內容
文章目錄
一、概覽
開機實際上是一件很複雜的事情,該動作的主要目的就是讓冷冰冰的機器幫助我們完成需要的工作。本文所介紹的,只是Linux系統的大致啓動過程
需要說明的是,近年來從底層的BIOS到上層的init程序都有了一些變化,而系統啓動的大致原理依舊,本章節先以“BIOS”來表示Legacy BIOS與UEFI,以GRUB表示引導程序,以INIT來表示各init程序……,大致說明系統啓動過程,後面的章節將分別介紹之
Linux啓動大致過程如下
我們知道,計算機只有在CPU加載到指令後才能根據指令完成工作,而其加載的指令存在於RAM(Random Access Memory,隨機訪問存儲器),即我們當前用作內存的介質,而該設備斷點後將無法保存數據,那麼此時指令從何而來?
在Linux系統初識-計算機體系結構中有介紹過,我們需要外部存儲設備來幫助持久保存數據。該設備即外存或輔儲,一般使用HDD或SSD爲介質
而這就需要在開機時將外存中的指令讀取到內存,而後加載到CPU,而這個動作本身,也是需要指令來完成的!這該如何進行?
這就需要計算機有“自舉”能力,現代計算機的設計中,在我們按下電源鍵後,主板將會把一段存儲在特殊存儲器上的代碼傳入CPU中,注意,該動作使用硬件邏輯完成的,不需要指令的參與,就像我們打開電燈開關,燈就會亮一樣
這段代碼我們將其稱之爲BIOS(Basic Input/Output System,基本輸入輸出系統),他主要負責探測硬件(POST(Power On Self Test,加電自檢))、選擇啓動設備
當上述操作無誤後,BIOS將選擇的設備中的代碼載入CPU,即Boot Loader,用於引導分區上的操作系統,在此處由於分區表類型不同稍有差異
- 對於完全支持UEFI引導:
- 對於BIOS引導:
由於BIOS本身不能識別文件系統,故要使用其他機制輔助,事實上,上圖對於BIOS的引導中,Boot Loader代碼也屬於Grub程序,而使用UEFI的引導中,Boot Loader即Grub,不同之處下文將詳細介紹,爲了方便敘述,本文的章節劃分按照上圖BIOS引導的架構
而後通過Grub實現從當前物理存儲設備選擇所啓動的操作系統,以及內核所在位置與相關啓動特性
上述操作完成後,根據Grub中指定的內核與相關參數啓動Kernel,在Kernel中啓動用戶空間的第一個進程,即init程序,至此,系統啓動完成
事實上init程序啓動後,還會有一些相關配置,此處沒有列出,下文將詳細介紹
二、BIOS
該過程是計算機加電之後運行的第一段程序,如今,UEFI即將全面取代BIOS,通常,我們將該程序稱爲固件(Firmware),負責硬件檢測,以及爲操作系統提供運行時服務
1. BIOS
BIOS(Basic Input/Output System,基本輸入輸出系統)固件安裝在PC的主板(Motherboard)上的獨立存儲器中,早期位於ROM(Read Only Memory,只讀存儲器)中,不可更改,後來位於閃存(Flash Memory)中(常爲EEPROM),帶來的好處是可以在不從主板上移除芯片的情況下重寫它,這允許對BIOS固件進行簡單的最終用戶更新,從而可以添加新功能或修復錯誤
通常,我們也將存儲BIOS的儲存器稱爲BIOS芯片
主要功能
-
BIOS中斷服務程序實質上是軟件與硬件之間的一個可編程接口,主要用於程序軟件功能與硬件之間連接。例如,系統對光驅、硬盤等管理,中斷的設置等
-
BIOS系統設置程序:BIOS提供一個“系統設置程序”,主要來設置系統底層的各項參數,如系統的基本情況、CPU特性、軟硬盤驅動器等部件的信息,該程序在開機時按某個鍵就可進入設置狀態
-
POST:接通電源後,系統首先由POST(Power On Self Test,加電自檢)程序來對內部各個設備進行檢查。通常完整的POST自檢將包括對CPU、640K基本內存、1M以上的擴展內存、ROM、等進行測試,一旦在自檢中發現問題,系統將給出提示信息或鳴笛警告,其測試流程如下1
引導系統重置REST引導CPU。
CPU指向BIOS自我測試的地址FFFFOH並打開CPU運行第一個指令。
CPU內部寄存器的測試。
CMOS 146818 SRAM檢查。
ROM BIOS檢查碼測試。
8254計時/計數器測試。
8237 DMA控制器測試。
74612頁寄存器測試。
REFRESH刷新電路測試。
8042鍵盤控制器測試。
DRAM 64KB基本存儲器測試。
CPU保護模式的測試。
8259中斷控制器的測試。
CMOS 146818電力及檢查碼檢查。
DRAM IMB以上存儲器檢查。
顯卡測試。
NMI強制中斷測試。
8254計時/計數器聲音電路測試。
8254計時/計數器計時測試。
CPU保護模式SHUT DOWN測試。
CPU回至實模式(REAL MODE)。
鍵盤鼠標測試。
8042鍵盤控制器測試。
8259中斷控制器IRQ0至IRQ18建立。
磁盤驅動器及界面測試。
設置並行打印機及串列RS232的界面。
檢查CMOS IC時間、日期。
檢查完成
- BIOS系統啓動自舉程序:系統完成POST自檢後,BIOS就首先按照系統CMOS設置中保存的啓動順序搜索軟硬盤驅動器及CD-ROM,網絡服務器等有效地啓動驅動器,讀入操作系統引導記錄,然後將系統控制權交給引導記錄,並由引導記錄來完成系統的順序啓動
CMOS與BIOS
很多人對二者傻傻分不清,這裏說明一下
BIOS是一段程序,存位於EEPROM(Electrically-Erasable Programmable Read-Only Memory,電可擦除可編程只讀存儲器),是一種可以通過電子方式多次複寫的半導體存儲設備,可以用特定的電壓,來抹除芯片上的信息,以便寫入新的數據(注意,早期的BIOS並非如此,上文有介紹)
而BIOS設置的配置記錄放在CMOS(Complementary Metal Oxide Semiconductor,互補金屬氧化物半導體)芯片中,該芯片屬於RAM,斷點後數據將丟失
故主板上有一塊電池,爲該存儲器供電,若取出電池,則可重置這些信息,如BIOS密碼、啓動次序、時間等
Boot Sequence
在BIOS提供的配置頁面中,提供了讓用戶選擇啓動次序(Boot Sequence)的接口,如下圖
上圖爲VMware Workstation 15的BIOS界面,實際界面樣式因不同主板或BIOS程序而異,然意義相同
配置啓動設備後,BIOS工作完成後將根據這裏配置的順序從對應設備中尋找啓動代碼,即查看該設備首512字節是否是以0x55
0xAA
結尾,若不是,則認爲該設備無啓動能力,繼續尋找下一個設備,否則加載該代碼,控制權移交至該代碼,BIOS工作完成
可參看Linux存儲管理相關內容
2. UEFI
UEFI(Unified Extensible Firmware Interface,統一可擴展固件接口)是一種個人計算機系統規格,用來定義操作系統與系統固件之間的軟件界面,作爲BIOS的替代方案
概述
UEFI的前身是Intel在1998年開始開發的Intel Boot Initiative,後來被重命名爲可擴展固件接口(Extensible Firmware Interface,縮寫EFI)。Intel在2005年將其交由統一可擴展固件接口論壇(Unified EFI Forum)來推廣與發展,爲了凸顯這一點,EFI也更名爲UEFI(Unified EFI)。UEFI論壇的創始者是11家知名計算機公司,包括Intel、IBM等硬件廠商,軟件廠商Microsoft,及BIOS廠商AMI(英語:American Megatrends)、Insyde及Phoenix
目前的最新版本爲UEFI-2.7A2
UEFI在概念上非常類似於一個小型的操作系統,並且具有操控所有硬件資源的能力,而其一些特性與操作系統有着本質區別
-
它只是硬件和預啓動軟件間的接口規範
-
UEFI環境下不提供中斷的機制,也就是說每個EFI驅動程序必須用輪詢(polling)的方式來檢查硬件狀態,並且需要以解釋的方式運行,較操作系統下的機械碼驅動效率更低
-
UEFI系統不提供複雜的緩存器保護功能,它只具備簡單的緩存器管理機制,具體來說就是指運行在x64或x86處理器的64位模式或保護模式下,以最大尋址能力爲限把緩存器分爲一個平坦的段(Segment),所有的程序都有權限訪問任何一段位置,並不提供真實的保護服務
UEFI的組成
x64計算機平臺的UEFI通常包含以下幾個部分:3
- Pre-EFI初始化模塊
- EFI驅動程序執行環境(DXE)
- EFI驅動程序
- 兼容性支持模塊(CSM)
- EFI應用程序
- GUID磁盤分區表
在實現中,統一可擴展固件接口(UEFI)初始化模塊和驅動執行環境通常被集成在一個只讀存儲器中(多爲NVRAM)
Pre-EFI初始化程序在系統開機的時候最先得到執行,完成存儲器的初始化工作,然後加載UEFI DXE(驅動程序執行環境)
當DXE被加載運行時,系統便具有了枚舉並加載其他UEFI驅動程序的能力。在基於PCI Express架構的x64計算機系統中,系統會加載UEFI內置的驅動程序模塊,完成UEFI固件、CPU、存儲器、芯片組及主板的進一步初始化,然後初始化各PCIe控制器、PCIe適配器(如RAID擴展卡或顯卡)及芯片組內置PCIe適配器(如芯片組內置的SATA、USB、網卡等功能)並加載這些PCIe設備的UEFI驅動程序(如果有的話,也有可能是加載PCIe設備的Legacy Option ROM)
UEFI驅動程序不僅可以包含在PCIe適配器的ROM中(作爲PCIe設備的UEFI Option ROM),還可以以.EFI文件的形式被方便的加載
在UEFI規範中,一種突破傳統MBR磁盤分區結構限制的GUID磁盤分區系統(GPT)被引入,新結構中,磁盤的主分區數不再受限制(在MBR結構下,只能存在4個主分區),另外UEFI+GPT磁盤分割表結合還可以支持2.1 TB以上硬盤,並且分區類型將由GUID來表示
GPT磁盤分區表的硬盤可包含EFI系統分區(ESP),EFI系統分區(ESP)可以被UEFI固件訪問,可用於存放操作系統的引導程序、EFI應用程序(如OEM的備份程序和硬件診斷程序)等等
EFI系統分區採用FAT文件系統,在Windows操作系統下默認在“本機”中隱藏。UEFI固件通過運行EFI系統分區中的引導程序文件(擴展名爲.EFI的UEFI應用程序)引導操作系統。CSM是在x86平臺UEFI系統中的一個特殊的模塊,它將爲不具備UEFI引導能力的操作系統以及16位的傳統Option ROM(即非EFI的Option ROM)提供類似於傳統BIOS的系統服務
Secure Boot功能要求原生UEFI(即關閉CSM),因此在UEFI固件設置中打開CSM前,需要在UEFI固件設置中關閉Secure Boot
下圖爲
引導
UEFI啓動
與BIOS不同,UEFI不依賴於引導扇區,而是將引導管理器定義爲UEFI規範的一部分。當計算機啓動時,啓動管理器會檢查啓動配置並根據其設置加載到內存中,然後執行指定的OS加載程序或操作系統內核。引導配置由存儲在NVRAM中的變量定義,包括指示OS加載器和OS內核的文件系統路徑的變量
UEFI可以自動檢測OS加載程序,從而可以從USB閃存驅動器等可移動設備輕鬆啓動。這種自動檢測依賴於到OS加載器的標準化文件路徑,路徑根據計算機體系結構而變化
從GPT分區磁盤引導UEFI系統通常稱爲UEFI-GPT引導。儘管UEFI規範要求完全支持MBR分區表[28],但某些UEFI固件實現會立即切換到基於BIOS的CSM引導,具體取決於引導磁盤分區表的類型,從而有效防止UEFI引導從MBR分區磁盤上的EFI系統分區。這樣的引導方案通常被稱爲UEFI-MBR
引導管理器通常具有文本用戶界面,因此用戶可以從可用引導選項列表中選擇所需的OS(或系統實用程序)
CSM啓動
爲了確保向後兼容性,PC級機器上的大多數UEFI固件實現還支持從MBR分區磁盤通過傳統BIOS模式啓動,通過提供傳統BIOS兼容性的兼容性支持模塊(CSM)。在這種情況下,通過忽略分區表並依賴引導扇區的內容,以與基於BIOS的傳統系統相同的方式執行引導
從MBR分區磁盤啓動BIOS樣式通常稱爲BIOS-MBR,無論是在UEFI還是基於BIOS的傳統系統上執行。此外,還可以從GPT磁盤啓動傳統的基於BIOS的系統,並且這種啓動方案通常稱爲BIOS-GPT
在兼容性支持模塊允許傳統的操作系統和一些選項ROM仍然使用不支持UEFI。它還提供了所需的傳統系統管理模式(SMM)功能,稱爲CompatibilitySmm,作爲UEFI SMM提供的功能的補充。這是可選的,高度芯片組和平臺特定。這種傳統SMM功能的一個示例是通過模擬其經典的PS / 2對應物,爲鍵盤和鼠標提供USB傳統支持
該方案作爲目前UEFI與BIOS的過度階段的緩衝,英特爾宣佈計劃到2020年逐步停止對CSM的支持
UEFI與BIOS在啓動過程上的區別
UEFI啓動過程
對應到UEFI個模塊爲,如下圖。事實上,左半部分中,SEC,PEI,DXE稱之爲PI(Platform Initialization)規範,UEFI純粹地是一個接口規範,它不會具體涉及平臺固件是如何實現的。“如何實現”這一內容是PI要解決的問題
BDS,TSL,和RT一起,屬於UEFI規範
- SEC階段
- SEC階段內存尚未被初始化,故UEFI將CPU緩存作爲內存使用,即Cache As RAM
- PEI階段
- 和BIOS的初始化階段類似,PEI階段用以喚醒CPU及內存初始化。PEI用SEC設置好的Cache As RAM,執行一些PEIM(初始化模塊),用於初始化一些硬件
- DXE階段:
- DXE的主要功能在加載驅動。此階段所有的內存、CPU、PCI、USB、SATA和Shell等都會被初始化
- BDS階段:
- 在BDS(引導設備選擇)階段,它負責執行所有符合UEFI驅動模型(UEFI driver model)的驅動。這是一個發現並一個個連接的過程,一個個啓動設備被發現,其設備路徑(device path)也被連接起來。在萬事俱備後,一個界面被顯示出來(嵌入式系統上可以沒有),供用戶進行設置和選擇啓動設備,這就是大家熟悉的BIOS界面,用戶可以自開機管理者程序頁,選擇要從哪個偵測到的開機設備來啓動
- TSL階段:
- 然後進入TSL(短暫系統載入)階段,由操作系統接手開機。除此之外,也可以在BDS階段選擇UEFI Shell,讓系統進入命令列,進行基本診斷和維護
BIOS啓動過程
BIOS啓動過程較爲簡單,一下做大致介紹
-
- 初始化
-
系統加電,CPU會自行重置爲初始狀態。BIOS boot block初始化階段啓動,此時內存尚未初始化,沒有內容可以執行,所以廠商讓CPU去尋找系統BIOS ROM中的reset vector(重置向量) :用一個固定的位置來啓動所謂的BIOS boot program
-
一般來說程序會在內存的
FFFF0h
處,也就是在UMA(上層記憶區域)靠結尾的地方。爲避免ROM大小改變造成兼容問題,所以一般會選擇放這裏。它的內容只有一個jump指令,進一步跳到真正的BIOS啓動程序 -
各家IBV (independent BIOS vender;獨立BIOS供應商)可以放在不同的位置,只要通過jump來指定即可
-
在該階段,系統的CPU、芯片組、Super I/O和USB只有部分初始化,僅獲取足夠信息來應付萬一BIOS開機失敗,可以利用其他儲存設備來救援BIOS的boot block
-
- POST
-
然後BIOS開始施行POST,它通常被放在內存
C0000h
處,作用是顯卡的初始化,而大部分的顯示卡都會在顯示器上顯示其相關訊息。這就是爲何各位在開機的時候,首先會在顯示器的畫面左上角出現有關顯示卡訊息的原因。 -
下一步BIOS會顯示啓動畫面,並開始更深入的檢測,如果這時候遇到任何錯誤,就會在畫面上顯示錯誤消息
-
- 記錄系統的配置
-
此時BIOS會對系統進行進一步的確認,看看你的電腦究竟安裝了那些系統資源或設備。有些電腦會逐步顯示這些被偵測到的設備,例如BIOS支持隨插即用,那它將會偵測和配置隨插即用裝置,並顯示由BIOS偵測到的隨插即用設備
-
在這些檢測結束後,BIOS會打出一個總結表於畫面上。而這個總結表在部分IBV的設定中是可以讓使用者開啓或關閉的。當然也有些IBV爲加速開機把這一步直接隱藏省略
-
- 提供常駐程序
- 提供操作系統或應用程序調用的中斷向量,如INT 10h(VGA圖形及文字輸出中斷)等
-
- 加載系統
- 到這裏是系統檢測的部分,接下來BIOS便開始尋找引導設備,用戶可以通過在BIOS的設定來決定搜尋順序
總結
此處將UEFI與BIOS的引導方式總結如下
- BIOS
-
BIOS只認識設備,不認識分區、不認識文件
-
啓動過程:根據CMOS中保存的順序,查看存儲設備,其前512字節是不是以0x55 0xAA結尾?若是則執行這段代碼,完成
- UEFI
-
UEFI認識設備,還認識設備ROM,還認識分區表、認識文件系統以及文件
-
啓動過程:經過一系列初始化後,按照設置裏的順序尋找啓動項,一般有兩種類型
- 文件啓動項,大約記錄的是某個磁盤的某個分區的某個路徑下的某個文件。對於文件啓動項,固件會直接加載這個EFI文件,並執行
- 設備啓動項,大約記錄的就是“某個U盤”、“某個硬盤”。(此處只討論U盤、硬盤)對於設備啓動項,UEFI標準規定了默認的路徑“\EFI\Boot\bootX64.efi”。UEFI會加載磁盤上的這個文件。文件不存在則失敗
-
UEFI-2以後,新增了SecureBoot功能。開了SecureBoot之後,主板會驗證即將加載的efi文件的簽名,如果開發者不是受信任的開發者,就會拒絕加載
三、Boot Loader
事實上在UEFI+GPT的引導方式下無需該步驟,從上文可看出,若使用該方式引導,由於UEFI可直接識別文件系統,在BDS階段選擇操作系統後即可進入下一步
本章主要介紹沒有使用GPT分區表或GPT分區表不被識別的情況,如
- BISO+MBR
- UEFI+MBR
- BIOS+GPT
此處糾正一個問題,很多人認爲BIOS+GPT無法引導,其實是可以的,上文已有介紹,GPT分區中LBA0位MBR兼容區。只是由於微軟在默認情況下不允許Windows操作系統通過BIOS引導GPT分區而已
然而我們也可以經過配置是的Windows在BIOS+GPT方式下啓動,chainloader指定ESP中的bootmgfw.efi即可
故對於BIOS與UEFI、BMR與GPT,其各種組合都是可以引導的,即
- BISO+MBR
- UEFI+MBR
- BIOS+GPT
- UEFI+GPT
若使用UEFI+MBR,則需要使用CSM,即打開兼容性支持模塊,如此,UEFI將會讀取MBR中的代碼,這段過程與BIOS+MBR基本無異
當BIOS(或使用SCM的UEFI)選擇到指定的啓動設備後,由於它不能識別文件系統,故將讀取選擇設備的首部446字節,這是一段代碼,即Boot Loader(引導加載器),由於代碼較爲簡短,無法執行復雜功能,故其主要用於將執行流執行另一部分
前面已經提及,Boot Loader爲Grub的一部分(第一部分),而上面指向的另一部分即Grub的第二部分
可參考Linux存儲管理-MBR相關內容
四、GRUB
1. Boot Loader
嚴格來講,該章節應該交Boot Loader,而由於上一章MBR中佔用,且如今Grub爲最著名的Boot Loader程序,此處將其命名爲GRUB
這裏對Boot Loader程序做簡要說明,該程序用於接管BIOS/UEFI交過來的控制系統權,用於加載系統內核
對於Windows,該程序爲ntloader,nt即New Technology,而Windows中更新的Boot Loader程序爲Windows Boot Manager
對於Linux平臺,有兩種較爲常見
-
LILO,即LInux,LOader,Linux加載器,不能引導1024柱面(Cylinder)以後分區上的內核,故不支持大硬盤,常用於嵌入式平臺
-
GRUB,即GRand Unified Bootloader
- Grub 0.x:Grub Legacy
- Grub 2
2. Grub概述
事實上,我們所謂的Grub應該被稱爲GNU Grub(就像我們每次說的Linux,Stallman先生都會強調:應該是GNU Linux!)
Grub 2引入了一些更爲有效的能力:
-
支持多種文件系統,如ext4、xfs、ntfs等
-
Grub 2可以訪問已經安裝的設備上的數據,可以直接從LAM和RAID中讀取數據
-
Grub 2使用了模塊機制,引入很多模塊,通過動態加載模塊來擴展功能,這樣允許core鏡像足夠小。
-
支持自動解壓
-
支持腳本語言,包括簡單的語法,如條件判斷,循環,變量和函數
-
國際化語音,包括支持非ASCII的字符集和類似gettext的消息分類,字體,圖形控制檯等
-
支持rescue模式,可用於系統無法引導的情況
-
Grub 2有更可靠的方法在磁盤上有多個文件系統時發現文件和目標內核,可以用命令發現系統設備編號或者是UUID
-
有一個靈活的命令接口。如果沒有配置文件的存在,grub2會自動進入命令模式
傳統Grub在運行時由三個階段
- Stage 1:位於MBR,用於引導Stage 2
- Stage 1_5:位於MBR之後的扇區,爲識別內核文件所在的文件系統提供文件系統識別擴展
- Stage 2:位於/boot分區,主要的引導工作在此完成
其中Stage 1_5非必要
3. Grub的安裝位置
這裏需要說明的文件爲
-
Boot.img:Stage 1對應的文件,MBR分區格式的磁盤中,放在MBR裏; GPT分區格式的磁盤中,放在Protective MBR中
-
Core.img:Stage 1_5對應的文件,32256字節大小。MBR分區格式的磁盤中,放在緊鄰MBR的若干扇區中;GPT分區格式的磁盤中,則放在34號扇區開始的位置(第一個分區所處的位置),而對應的GPT分區表中的第一個分區的entry被置空
-
/boot/grub:步驟2對應的文件目錄,放在系統分區或者單獨的Boot分區中
- Grub程序各部分安裝的位置如圖
-
- MBR分區表:
- MBR分區表:
-
- GPT分區表
- GPT分區表
4. 啓動Kernel前的準備
在Grub加載Kernel後,Kernel將啓動init程序,以下爲./linux.init/main.c
部分代碼:
static int __ref kernel_init(void *unused)
{
kernel_init_freeable();
/* need to finish all async __init code before freeing the memory */
async_synchronize_full();
free_initmem();
mark_rodata_ro();
system_state = SYSTEM_RUNNING;
numa_default_policy();
flush_delayed_fput();
if (ramdisk_execute_command) {
if (!run_init_process(ramdisk_execute_command))
return 0;
pr_err("Failed to execute %s\n", ramdisk_execute_command);
}
/*
* We try each of these until one succeeds.
*
* The Bourne shell can be used instead of init if we are
* trying to recover a really broken machine.
*/
if (execute_command) {
if (!run_init_process(execute_command))
return 0;
pr_err("Failed to execute %s. Attempting defaults...\n",
execute_command);
}
if (!run_init_process("/sbin/init") ||
!run_init_process("/etc/init") ||
!run_init_process("/bin/init") ||
!run_init_process("/bin/sh"))
return 0;
panic("No init found. Try passing init= option to kernel. "
"See Linux Documentation/init.txt for guidance.");
}
內核會從三出搜索該程序,若依然沒有找到,則啓動一個shell,這些程序位於/
(根)下,故而此時Kernel需要有加載根文件系統的能力,而/
的文件系統與/boot
可以位於不同分區,加之Kernel中不可能將所有文件系統的驅動都包含,而此時需要如何訪問/
?
我們知道,Boot Loader程序有時需要藉助Stage 1_5階段來加載/boot
所在分區的相應驅動
同樣的,將相關文件系統的驅動做成一個特定文件,在Kernel訪問/
之前,先加載該文件即可
顯然,該文件需要內核能直接訪問,故其在/boot
中,在CentOS 5中,該文件爲ramdisk
,對應文件名一般爲initrd
,而在CentOS 6之後,該文件爲ramfs
,對應文件名一般爲initramfs
從名稱上可以看出,CentOS 5中通過將RAM模擬爲塊設備,而Linux的緩存機制導致將可能再次在RAM中緩存該內容,造成不必要的浪費,而ramfs本身就是一個tmpfs的內存盤,擁有最小化的設計,繞過了緩存機制,也消除了多餘的內存佔用
因此,Kernel與initrd(或initramfs)必須存儲在Boot Loader程序可以訪問的位置,並且需要將initrd(或initramfs)加載後傳遞其地址給Kernel,如此,內核即可訪問根文件系統
5 .Grub Legacy
功能
-
提供菜單,選擇要啓動時的內核或系統;
- 允許傳遞參數給內核
- 可以隱藏選擇界面
-
提供交互式接口
e
:編輯模式,用於編輯菜單c
:命令模式,交互式接口
-
基於密碼的保護
- 啓用內核映像,定義在相應的
title
下 - 傳遞參數,即進入編輯模式,定義在全局段中
- 啓用內核映像,定義在相應的
配置文件
配置文件的讀取主要在Stage 2完成,其配置文件爲/etc/grub.conf
,該文件指向/boot/grub/grub.conf
,如下爲RHEL 5中的一個實例,以之爲例說明個字段意義
default=0 # 設定默認啓動的title的編號,從0開始
timeout=5 # 等待用戶選擇的內核或OS超時時長,單位:秒
splashimage=(hd0,0)/grub/splash.xpm.gz
# 指定grub的背景圖片,gimp工具可以編輯圖片,要保存爲.xpm格式,然後使用gzip壓縮(.gz)
hiddenmenu # 隱藏菜單
password redhat # grub的密碼(明文),菜單編輯密碼
password --md5 $1$HKXJ51$B9Z8A.X//XA.AtzU1.KuG.
# grub加密密碼,可以使用grub-md5-crypt命令來計算密碼
title Red Hat Enterprise Linux Server (2.6.18-308.el5)
# 內核標題,或操作系統名稱,字符串,可自由修改
root (hd0,0)
# 內核文件所在的設備;對grub而言,所有類型硬盤一律hd,格式爲
(hd#,N);
# hd#, #表示第幾個磁盤;從0開始編號
# N表示對應磁盤的分區;從0開始編號
kernel /vmlinuz-2.6.18-308.el5 ro root=/dev/vol0/root rhgb quiet
# 內核文件路徑,及傳遞給內核的參數,參數即/proc/cmdline中的內容
# 參數: ro root=/path/to/DEVICE
# 將/path/to/DEVICE所代表的設備當做內核啓動時的根,以只讀方式掛載
# quiet:靜默模式, 內核初始化的信息不再輸出
initrd /initrd-2.6.18-308.el5.img
# 文件:通常爲cpio歸檔,並使用gzip壓縮,通常以.img作爲擴展名
# ramdisk文件路徑,即臨時的根,是一個完整意義上的Linux
# 注意:以上兩項顯示根下的文件是由於文件位於/boot/目錄,該目錄是單獨的分區,而此時沒有文件系統,遂grub直接訪問該分區
# 若/boot沒有單獨分區,則會正常顯示
password --md5 $1$HKXJ51$B9Z8A.X//XA.AtzU1.KuG. # 將該字段放置於所有title上面,爲全局密碼,放在某一title中,爲內核啓動密碼
title Install Red Hat Enterprise Linux 5
root (hd0,0)
kernel /vmlinuz-5 ks=http://172.16.0.1/workstation.cfg ksdevice=eth0 noipv6
initrd /initrd-5
password --md5 $1$FSUEU/$uhUUc8USBK5QAXc.BfW4m.
命令行
help:獲取幫助列表
help KEYWORD:命令詳細幫助
find:查找文件
find (hd#,N)/PATH/TO/SOMEFILE
設定根設備後可省略設備
root:設定根設備
root (hd#,N)
kernel:指定本次啓動使用的kernel
kernel /PATH/TO/KERNEL_FILE
額外可添加內核支持使用的cmdline參數
init=/PATH/TO/INIT
selinux=0
root=/PATH/TO/ROOT
…
initrd:爲選定的內核提供額外文件的ramdisk
initrd /PATH/TO/INITRAMFS_FILE
該文件版本需要與kernel版本完全匹配
boot:引導啓動選定的內核
安裝grub
可使用grub-install
命令安裝grub,使用方式爲
grub-install --root-directory=DIR /dev/DISK
還可以在grub交互界面安裝:
grub> root (hd#,#)
grub> setup (hd#)
- grub指定設備的方式
-
hd(#,#)
hd#
: 磁盤編號,用數字表示;從0開始編號#
: 分區編號,用數字表示; 從0開始編號
手動在grub命令行接口啓動系統
grub> root (hd#,#)
grub> kernel /vmlinuz-VERSION-RELEASE ro root=/dev/DEVICE
grub> initrd /initramfs-VERSION-RELEASE.img
grub> boot
6. Grub 2
Grub 2的軟件包名即grub2,他與Grub Legacy的區別上文已有介紹
配置文件
-
/boot/grub2/grub.cfg
:啓動項配置,可由grub2-mkconfig
生成 -
/etc/default/grub
:grub2-mkconfig
工具生成配置時的參考信息 -
/etc/grub.d/*
:該目錄下主要爲一些腳本,分別配合對應grub.cfg
上的各個部分
應用
- 查看當前默認啓動項
grub2-editenv list
- 設置默認啓動項
- 方式一:
grub2-set-default
- 方式二:修改
/etc/default/grub
,修改GRUB_DEFAULT=#
(#
:該數字爲grub菜單中各啓動項的順序),而後使用grub2-mkconfig -o /boot/grub2/grub.cfg
生成配置文件 - 安裝grub2
-
grub2-install [--root-directory=/PATH/TO/ROOT] [DEVICE] 若爲UEFI,則DEVICE可省略
- 生成新的grub.cfg文件
-
grub2-mkconfig -o /boot/grub2/grub.cfg
五、Kernel
Grub工作完成後,Kernel接管控制權,在此其主要工作爲:
- 設備探測
- 驅動初始化(可能會從initrd(在redhat6中叫做initramfs)文件中裝載驅動模塊)
- 以只讀方式掛載根文件系統(稍後init會重新掛載文件系統)
- 裝載第一個進程init(PID: 1)
grub中指定的initrd(或initramfs)在此處將會用到,另外,第一個進程在CentOS 7中稱爲systemd,下一章將介紹
在內核的實現中,我們介紹了當前操作系統內核實現的兩種主流方式
- 微內核將通過各內核子系統實現管理工作,如Windows,Solaris
- 宏內核將各種功能集於一身,Linux內核就是這種設計方式
理論上講,微內核的設計思想更爲先進,而事實上要協調好各個子系統去實現複雜管理任務,這本身也是一個非常複雜的工作
Linux內核通過將個功能分爲不同的模塊,按需動態裝卸載,這些模塊在Kernel 2.6版本以後本稱爲Kernel Object,文件名後綴爲.ko
(之前爲.o
)
BTW,在Linux中共享庫爲Shared Object(.so
) 共享對象,在Windows中爲Dynamic Link Library(.dll
) 動態鏈接庫
Linux內核文件一般位於/boot/vmlinuz-VERSION-RELEASE
,而其模塊文件爲/lib/modules/VERSION-RELEASE/
,而上文介紹的ramdisk,在CentOS 5中位於/boot/initrd-VERSION-RALEASE.img
,而在CentOS 6之後的版本爲/boot/initramfs-VERSION-RELEASE.img
:
[root@localhost ~]# ll /boot/vmlinuz-`uname -r` -h
-rwxr-xr-x. 1 root root 4.8M Mar 6 2015 /boot/vmlinuz-3.10.0-229.el7.x86_64
[root@localhost ~]# ll /lib/modules/`uname -r` -h
total 2.6M
lrwxrwxrwx. 1 root root 38 Dec 20 04:15 build -> /usr/src/kernels/3.10.0-229.el7.x86_64
drwxr-xr-x. 2 root root 6 Mar 6 2015 extra
drwxr-xr-x. 11 root root 4.0K Dec 20 04:15 kernel
-rw-r--r--. 1 root root 668K Dec 20 04:22 modules.alias
-rw-r--r--. 1 root root 644K Dec 20 04:22 modules.alias.bin
-rw-r--r--. 1 root root 1.3K Mar 6 2015 modules.block
-rw-r--r--. 1 root root 5.8K Mar 6 2015 modules.builtin
-rw-r--r--. 1 root root 7.5K Dec 20 04:22 modules.builtin.bin
-rw-r--r--. 1 root root 209K Dec 20 04:22 modules.dep
-rw-r--r--. 1 root root 304K Dec 20 04:22 modules.dep.bin
-rw-r--r--. 1 root root 339 Dec 20 04:22 modules.devname
-rw-r--r--. 1 root root 108 Mar 6 2015 modules.drm
-rw-r--r--. 1 root root 108 Mar 6 2015 modules.modesetting
-rw-r--r--. 1 root root 1.5K Mar 6 2015 modules.networking
-rw-r--r--. 1 root root 82K Mar 6 2015 modules.order
-rw-r--r--. 1 root root 165 Dec 20 04:22 modules.softdep
-rw-r--r--. 1 root root 285K Dec 20 04:22 modules.symbols
-rw-r--r--. 1 root root 356K Dec 20 04:22 modules.symbols.bin
lrwxrwxrwx. 1 root root 5 Dec 20 04:15 source -> build
drwxr-xr-x. 2 root root 6 Mar 6 2015 updates
drwxr-xr-x. 2 root root 91 Dec 20 04:15 vdso
drwxr-xr-x. 2 root root 6 Mar 6 2015 weak-updates
[root@localhost ~]# ll /boot/initramfs-`uname -r`.img -h
-rw-------. 1 root root 20M Jan 18 13:06 /boot/initramfs-3.10.0-229.el7.x86_64.img
在RHEL系列發行版中,/lib/modules/VERSION-RELEASE/
中有對應內核所需的各種外圍模塊,依賴關係由內核(依賴關係文件modules.dep
)處理
kernel
目錄中的內容爲內核主要模塊:
目錄 | 說明 |
---|---|
arch |
平臺相關,驅動CPU |
crypto |
加密解密 |
drivers |
驅動 |
fs |
文件系統 |
kernel |
內核自身的額外功能 |
lib |
庫 |
mm |
Memory Management,內存管理 |
net |
網絡(不是驅動,而是網絡協議棧的實現) |
sound |
聲卡 |
另外,ramdis由於取藥提供文件系統支持,而用戶的情況有各不相同,故該文件在安裝操作系統時生成,我們亦可自行使用工具生成之:
- CentOS 5:
mkinitrd
- CentOS 6+:
mkinitrd
、dracut
六、init
內核初始化的最後一步就是啓動 pid 爲 1 的 init 進程。這個進程是系統的第一個進程。它負責產生其他所有用戶進程
init 以守護進程方式存在,是所有其他進程的父進程
Init 系統能夠定義、管理和控制 init 進程的行爲。它負責組織和運行許多獨立的或相關的始化工作(因此被稱爲 init 系統),從而讓計算機系統進入某種用戶預訂的運行模式
僅僅將內核運行起來是毫無實際用途的,必須由 init 系統將系統代入可操作狀態。比如啓動外殼 shell 後,便有了人機交互,這樣就可以讓計算機執行一些預訂程序完成有實際意義的任務。或者啓動 X 圖形系統以便提供更佳的人機界面,更加高效的完成任務。這裏,字符界面的 shell 或者 X 系統都是一種預設的運行模式
大多數 Linux 發行版的 init 系統是和 System V 相兼容的,被稱爲 sysvinit。這是人們最熟悉的 init 系統。一些發行版如 Slackware 採用的是 BSD 風格 Init 系統,這種風格使用較少,本文不再涉及。其他的發行版如 Gentoo 是自己定製的。Ubuntu 和 RHEL 採用 upstart 替代了傳統的 sysvinit
,啓動系統的第一個進程,在RHEL系列的各個發行版中,該程序亦各不相同
-
- CentOS5
- SysV init,進程串行啓動
- 配置文件:
/etc/inittab
-
- CentOS6
- Upstart,採用D-Bus、事件驅動模型等新機制4
- 配置文件:
/etc/inittab
,/etc/init/*.conf
-
- CentOS7
-
Systemd
-
配置文件:
/usr/lob/systemd/system
,/etc/systemd/system
-
完全兼容SysV腳本機制,service命令依然可用,建議使用
systemctl
命令來控制服務5
在 Linux 主要應用於服務器和 PC 機的時代,SysVinit 運行非常良好,概念簡單清晰。它主要依賴於 Shell 腳本,這就決定了它的最大弱點:啓動太慢。在很少重新啓動的 Server 上,這個缺點並不重要。而當 Linux 被應用到移動終端設備的時候,啓動慢就成了一個大問題。爲了更快地啓動,人們開始改進 sysvinit,先後出現了 upstart 和 systemd 這兩個主要的新一代 init 系統
1. SysV init
2. Upstart init
3. systemd
七、初始化
服務相關內容後續將做介紹 ↩︎