本文參考了如下文章
深入理解linux啟動過程
mbr (主引導記錄(Master Boot Record))
電腦從開機加電到操作系統main函數之前執行的過程
詳解linux系統的啟動過程及系統初始化
關於linux系統的啟動流程我們可以按步進行劃分為如下:
BIOS電腦啟動後,CPU邏輯電路被設計為只能運行內存中的程序,沒有能力直接運行存在於軟盤或硬盤中的操作系統,如果想要運行,必須要加載到內存(RAM)中。
BIOS是如何啟動的,CPU硬件邏輯設計為在加電瞬間強行將CS值置為0XF000,IP為0XFFF0,這樣CS:IP就指向0XFFFF0這個位置,這個位置正是BIOS程序的入口地址。
BIOS程序被固化在計算機主機板上的一塊很小的ROM芯片裡。現在CS:IP已經指向了0XFFFF0這個位置,意味著BIOS開始啟動。
BIOS的第一步動作就是進行上電自檢(POST)
POST的工作是檢查硬件設備。隨著BIOS程序的執行,屏幕上會顯示顯卡的信息,內存的信息等,
BIOS的第二步動作就是枚舉本地設備並初始化
有一項對啟動操作系統至關重要的工作,那就是BIOS在內存中建立中斷向量表和中斷服務程序
BIOS程序在內存最開始的位置(0x00000)用1KB的內存空間(0x00000~0x003FF)構建中斷向量表,在緊挨著它的位置用256KB的內存空間構建BIOS數據區(0x00400~0x004FF),並在大約57KB以後得位置(0x0e05b)加載了8KB左右的與中斷向量表相應的若干中斷服務程序。
中斷向量表有256個中斷向量,每個中斷向量占4個字節,其中兩個字節是CS值,兩個字節是IP值。每個中斷向量都指向一個具體的中斷服務程序。
由於BIOS功能使用上的不同,它由兩個部分組成:POST和runtime服務。POST完成後,它將從存儲器中被清除,但是BIOS runtime服務會被保留,用於目標操作系統。
為了啟動操作系統,BIOS的runtime服務將搜索那些激活狀態的或是可引導啟動的設備,搜索的順序則由CMOS設置決定(也就是我們平時所謂的在BIOS中設置的啟動順序)。一個軟驅,一台光驅,一個硬盤上的分區,網絡上的設備甚至一個usb 閃存盤都可以作為一個啟動設備。
當然,linux通常是從硬盤啟動的。硬盤上的MBR(主啟動記錄)包含有基本的boot loader,它是一個512字節大小的扇區,位於磁盤的第一個扇區(0磁頭0磁道1扇區)。當MBR被裝載到RAM中後,BIOS就會將控制權轉交給MBR。
位於MBR中的主boot loader是一個512字節的鏡像,其中不僅包含了bootload程序代碼,還包含了一個小的分區表。
最初的446字節是主boot loader,它裡面就包含有可執行代碼以及錯誤消息文本。接下來的64字節是分區表,其中包含有四個分區的各自的記錄(一個分區占16字節)。MBR通過特殊數字0xAA55(譯者注:在電子界中AA55確實是具有傳奇色彩的數字,想知道為什麼麼?將它展開成二進制形式,看看有什麼規律)作為兩個字節的結束標志。0x55AA同時也是MBR有效的校驗確認。
首先對CPU發送int 0x19中斷,使CPU運行int 0x19中斷對應的中斷服務程序,這個中斷服務程序的作用就是把軟盤第一個扇區的程序加載到內存的指定位置。
主boot loader的工作是尋找並加載次boot loader(內核加載程序)
它通過分析分區表,找出激活分區來完成這個任務,當它找到一個激活分區時,它將繼續掃描剩下的分區表中的分區,以便確認他們都是未激活的。
確認完畢後,激活分區的啟動記錄(次boot loader)從設備中被讀到RAM,並被執行。
其中加載過程需要借助BIOS提供的int 0x13中斷向量指向的中斷服務程序來完成。該程序將軟盤第二個扇區開始的4個扇區,即setup.s對應的程序加載至內存的SETUPSEG(0x90200)處。
把第一階段和第二階段的boot loaders聯合起來,就是在x86個人電腦中,我們所說的linux loader(LILO)或者GRand Unified Bootloader(GRUB)。由於GRUB修正了一些LILO中存在的缺陷,因此下面就讓我們來看看GRUB(如果你希望得到更多的關於GRUB,LILO和與之相關話題的討論資源,請見文後的參考資料)
對於GRUB來說,一個比較好的方面就是它包含了linux文件系統的知識。與LILO使用裸扇區不同的是,GRUB能夠從ext2或者ext3文件系統中加載linux內核。它是通過將本來兩階段的boot loader轉換成三個階段的boot loader。在第一階段(MBR)中會啟動stage1.5的boot loader來理解linux內核鏡像中的特殊的文件系統格式,例如,reiserfs_stage1-5(用於從reiserf日志文件系統中進行加載)或e2fs+stage1_5(用於從wxt2或ext3文件系統進行加載)。當stage1.5的boot loader被加載並運行時,stage2 的boot loader才能被加載。當stage2被加載時,GRUB能根據請求的情況顯示一個可選內核的清單(在 /etc/grub.conf 中進行定義,同時還有幾個軟符號鏈接 /etc/grub/menu.lst 和 /etc/grub.conf)。你可以選擇一個內核,修改其附加的內核參數。同時,你可以選擇使用命令行的shell來對啟動過程進行更深層次的手工控制。
在次boot loader存在與內存中後,就可以對文件系統進行查詢了,同時將默認的內核鏡像以及初始化內存盤鏡像也被加載到內存中。
一切准備完畢之後,次boot loader就會調用內核鏡像,完成操作系統的加載。
當內核映像被加載到內存中(加載過程仍然用int 0x13中斷向量),並且次引導加載程序釋放控制權之後,內核階段就開始了。
內核映像並不是一個可執行的內核,而是一個壓縮過的內核映像。通常它是一個 zImage(壓縮映像,小於 512KB)或一個 bzImage(較大的壓縮映像,大於 512KB),它是提前使用 zlib 進行壓縮過的。在這個內核映像前面是一個例程,它實現少量硬件設置,並對內核映像中包含的內核進行解壓,然後將其放入高端內存中,如果有初始 RAM 磁盤映像,就會將它移動到內存中,並標明以後使用。然後該例程會調用內核,並開始啟動內核引導的過程。
當 bzImage(用於 i386 映像)被調用時,我們從 ./arch/i386/boot/head.S 的 start 匯編例程開始執行。
這個例程會執行一些基本的硬件設置,並調用 ./arch/i386/boot/compressed/head.S 中的 startup_32,設置一個基本的環境(堆棧等),並清除 Block Started by Symbol(BSS)。然後調用一個叫做 decompress_kernel 的 C 函數(在 ./arch/i386/boot/compressed/misc.c 中)來解壓內核。當內核被解壓到內存中之後,就可以調用它了。這是另外一個 startup_32 函數,但是這個函數在 ./arch/i386/kernel/head.S 中。
進入保護模式
設置中斷描述附表和全局描述符表
創建了內存分頁機制
start_kernel啟動內核
創建init進程
上個世紀70年代初,”只讀內存”(read-only memory,縮寫為ROM)發明,開機程序被刷入ROM芯片,計算機通電後,第一件事就是讀取它。
計算機,啟動這塊芯片裡的程序叫做”基本輸出輸入系統”(Basic Input/Output System),簡稱為BIOS。
它是一組固化到計算機內主板上一個ROM芯片上的程序,它保存著計算機最重要的基本輸入輸出的程序、開機後自檢程序和系統自啟動程序,它可從CMOS中讀寫系統設置的具體信息。 其主要功能是為計算機提供最底層的、最直接的硬件設置和控制。
BIOS芯片中主要存放:
自診斷程序:通過讀取CMOSRAM中的內容識別硬件配置,並對其進行自檢和初始化;
CMOS設置程序:引導過程中,用特殊熱鍵啟動,進行設置後,存入CMOS RAM中;
系統自舉裝載程序:在自檢成功後將磁盤相對0道0扇區上的引導程序裝入內存,讓其運行以裝入DOS系統;
主要I/O設備的驅動程序和中斷服務:由於BIOS直接和系統硬件資源打交道,因此總是針對某一類型的硬件系統,而各種硬件系統又各有不同,所以存在各種不同種類的BIOS,隨著硬件技術的發展,同一種BIOS也先後出現了不同的版本,新版本的BIOS比起老版本來說,功能更強。
BIOS:計算機加電自檢完成後第一個讀取的地方就是就是BIOS(Basic Input Output System,基礎輸入輸出系統),BIOS裡面記錄了主機板的芯片集與相關設置,如CPU與接口設備的通信頻率、啟動設備的搜索順序、硬盤的信息、系統時間、內存信息、時鐘信息、PnP特性、外部總線、各種接口設備的I/O地址、已經與CPU通信的IRQ中斷信息,所以,啟動如果要順利啟動,首先要讀取BIOS設置。
計算機會首先加載BIOS信息,BIOS信息是如此的重要,以至於計算機必須在最開始就找到它。
電腦啟動後,CPU邏輯電路被設計為只能運行內存中的程序,沒有能力直接運行存在於軟盤或硬盤中的操作系統,如果想要運行,必須要加載到內存(RAM)中。
CPU硬件邏輯設計為在加電瞬間強行將CS值置為0XF000,IP為0XFFF0,這樣CS:IP就指向0XFFFF0這個位置,這個位置正是BIOS程序的入口地址。
BIOS需要在內存中加載中斷向量表和中斷服務程序
BIOS程序被固化在計算機主機板上的一塊很小的ROM芯片裡。現在CS:IP已經指向了0XFFFF0這個位置,意味著BIOS開始啟動。隨著BIOS程序的執行,屏幕上會顯示顯卡的信息,內存的信息,說明BIOS程序在檢測顯卡,內存,這個就是POST開機自檢期間,有一項對啟動操作系統至關重要的工作,那就是BIOS在內存中建立中斷向量表和中斷服務程序
BIOS程序在內存最開始的位置(0x00000)用1KB的內存空間(0x00000~0x003FF)構建中斷向量表,在緊挨著它的位置用256KB的內存空間構建BIOS數據區(0x00400~0x004FF),並在大約57KB以後得位置(0x0e05b)加載了8KB左右的與中斷向量表相應的若干中斷服務程序。
中斷向量表有256個中斷向量,每個中斷向量占4個字節,其中兩個字節是CS值,兩個字節是IP值。每個中斷向量都指向一個具體的中斷服務程序。
BIOS程序首先檢查,計算機硬件能否滿足運行的基本條件,這叫做”硬件自檢”(Power-On Self-Test),縮寫為POST。
如果硬件出現問題,主板會發出不同含義的蜂鳴,啟動中止。如果沒有問題,屏幕就會顯示出CPU、內存、硬盤等信息。
電腦主機打開電源的時候,隨後會聽到滴的一聲,系統啟動開始了開機自檢(POST-power on self test)自檢開始)
這個過程中主要是檢測計算機硬件設備比如:CPU,內存,主板,顯卡,CMOS等設備是否有故障存在
如果有硬件故障的話將按兩種情況理:
對於嚴重故障(致命性故障)則停機,此時由於各種初始化操作還沒完成,不能給出任何提示或信號;
對於非嚴重故障則給出提示或聲音報警信號,等待用戶處理),如果沒有故障,POST完整自己的接力任務,將尾部工作交接給BIOS處理
BIOS把控制權轉交給下一階段的啟動程序。
這時,BIOS需要知道,”下一階段的啟動程序”具體存放在哪一個設備。也就是說,BIOS需要有一個外部儲存設備的排序,排在前面的設備就是優先轉交控制權的設備。這種排序叫做”啟動順序”(Boot Sequence)。
打開BIOS的操作界面,裡面有一項就是”設定啟動順序”。
在此之後,計算機心裡就有譜了,知道應該去讀取哪個硬件設備了。
硬件自檢完成後,我們期望能否啟動操作系統,但是問題出來了
* 操作系統存放在哪?
* BIOS如何找到操作系統?
* BIOS如何加載操作系統?
為了尋找操作系統,BIOS按照”啟動順序”,把控制權轉交給排在第一位的儲存設備。
這時,計算機讀取該設備的第一個扇區,也就是讀取最前面的512個字節。
如果這512個字節的最後兩個字節是0x55和0xAA,表明這個設備可以用於啟動;
如果不是,表明設備不能用於啟動,控制權於是被轉交給”啟動順序”中的下一個設備。
這最前面的512個字節,就叫做“主引導記錄”(Master boot record,縮寫為MBR)
位於MBR中的主boot loader是一個512字節的鏡像,其中不僅包含了程序代碼,還包含了一個小的分區表。
最初的446字節是主boot loader,它裡面就包含有可執行代碼以及錯誤消息文本。接下來的64字節是分區表,其中包含有四個分區的各自的記錄(一個分區占16字節)。MBR通過特殊數字0xAA55(譯者注:在電子界中AA55確實是具有傳奇色彩的數字,想知道為什麼麼?將它展開成二進制形式,看看有什麼規律)作為兩個字節的結束標志。0x55AA同時也是MBR有效的校驗確認。
主boot loader的工作是尋找並加載次boot loader。它通過分析分區表,找出激活分區來完成這個任務,當它找到一個激活分區時,它將繼續掃描剩下的分區表中的分區,以便確認他們都是未激活的。確認完畢後,激活分區的啟動記錄從設備中被讀到RAM,並被執行。
“主引導記錄”只有512個字節,放不了太多東西。它的主要作用是,告訴計算機到硬盤的哪一個位置去找操作系統。
主引導記錄由三個部分組成:
第1-446字節:調用操作系統的機器碼。
第447-510字節:分區表(Partition table)。
第511-512字節:主引導記錄簽名(0x55和0xAA)。
其中,第二部分”分區表”的作用,是將硬盤分成若干個區。
硬盤分區有很多好處。考慮到每個區可以安裝不同的操作系統,”主引導記錄”因此必須知道將控制權轉交給哪個區。分區表的長度只有64個字節,裡面又分成四項,每項16個字節。所以,一個硬盤最多只能分四個一級分區,又叫做“主分區”。
每個主分區的16個字節,由6個部分組成:
第1個字節:如果為0x80,就表示該主分區是激活分區,控制權要轉交給這個分區。四個主分區裡面只能有一個是激活的。
第2-4個字節:主分區第一個扇區的物理位置(柱面、磁頭、扇區號等等)。
第5個字節:主分區類型。
第6-8個字節:主分區最後一個扇區的物理位置。
第9-12字節:該主分區第一個扇區的邏輯地址。
第13-16字節:主分區的扇區總數。
最後的四個字節(”主分區的扇區總數”),決定了這個主分區的長度。也就是說,一個主分區的扇區總數最多不超過2的32次方。
如果每個扇區為512個字節,就意味著單個分區最大不超過2TB。再考慮到扇區的邏輯地址也是32位,所以單個硬盤可利用的空間最大也不超過2TB。
如果想使用更大的硬盤,只有2個方法:
一是提高每個扇區的字節數,
二是增加扇區總數。
MBR:第一個可開機設備的第一個扇區內的主引導分區塊,內包含引導加載程序
引導加載程序(Boot loader): 一支可讀取內核文件來執行的軟件
內核文件: 開始操作系統的功能
由硬盤啟動時,BIOS通常是轉向第一塊硬盤的第一個扇區,即主引導記錄(MBR)。
裝載GRUB和操作系統的過程,包括以下幾個操作步驟:
裝載記錄
基本引導裝載程序所做的唯一的事情就是裝載第二引導裝載程序。
裝載Grub
這第二引導裝載程序實際上是引出更高級的功能,以允許用戶裝載一個特定的操作系統。
裝載系統
如linux內核。GRUB把機器的控制權移交給操作系統。
不同的是,微軟操作系統都是使用一種稱為鏈式裝載的引導方法來啟動的,主引導記錄僅僅是簡單地指向操作系統所在分區的第一個扇區。
眾所周知,硬盤上第0磁道第一個扇區被稱為MBR,也就是Master Boot Record,即主引導記錄,它的大小是512字節,別看地方不大,可裡面卻存放了預啟動信息、分區表信息。
按照BIOS所設定的系統啟動流程,如果檢測通過,則根據引導次序(Boot Sequence)開始在第一台設備上支持啟動程序,我們的啟動設備主要包括硬盤、USB、SD等,我們一般用的是硬盤,然後進行讀取第一個設備就是硬盤,第一個要讀去的就是該硬盤的主引導記錄MBR(Master Boot Record),然後系統可以根據啟動區安裝的引導加載程序(Boot Loader)開始執行核心識別的工作。
MBR程序只是找到只是硬盤分區內最前面的446個字節的Boot Loader,然後查找相關配置和定義。
然後將控制權交給主引導代碼。主引導代碼的任務包括
掃描分區表,找到一個激活(可引導)分區;
找到激活分區的起始扇區;
將激活分區的引導扇區裝載到內存7C00處;
將控制權交給引導扇區代碼;
系統讀取內存中的grub配置信息(一般為menu.lst或grub.lst),並依照此配置信息來啟動不同的操作系統。
這時,計算機的控制權就要轉交給硬盤的某個分區了,這裡又分成三種情況。
情況A:卷引導記錄
上一節提到,四個主分區裡面,只有一個是激活的。計算機會讀取激活分區的第一個扇區,叫做“卷引導記錄”(Volume boot record,縮寫為VBR)。
“卷引導記錄”的主要作用是,告訴計算機,操作系統在這個分區裡的位置。然後,計算機就會加載操作系統了。
情況B:擴展分區和邏輯分區
隨著硬盤越來越大,四個主分區已經不夠了,需要更多的分區。但是,分區表只有四項,因此規定有且僅有一個區可以被定義成“擴展分區”(Extended partition)。所謂“擴展分區”,就是指這個區裡面又分成多個區。這種分區裡面的分區,就叫做”邏輯分區”(logical partition)。
計算機先讀取擴展分區的第一個扇區,叫做“擴展引導記錄”(Extended boot record,縮寫為EBR)。它裡面也包含一張64字節的分區表,但是最多只有兩項(也就是兩個邏輯分區)。
計算機接著讀取第二個邏輯分區的第一個扇區,再從裡面的分區表中找到第三個邏輯分區的位置,以此類推,直到某個邏輯分區的分區表只包含它自身為止(即只有一個分區項)。因此,擴展分區可以包含無數個邏輯分區。
但是,似乎很少通過這種方式啟動操作系統。如果操作系統確實安裝在擴展分區,一般采用下一種方式啟動。
情況C:啟動管理器在這種情況下,計算機讀取”主引導記錄”前面446字節的機器碼之後,不再把控制權轉交給某一個分區,而是運行事先安裝的“啟動管理器”(boot loader),由用戶選擇啟動哪一個操作系統。
Linux環境中,目前最流行的啟動管理器是Grub。
Boot Loader 就是在操作系統內核運行之前運行的一段小程序。通過這段小程序,我們可以初始化硬件設備、建立內存空間的映射圖,從而將系統的軟硬件環境帶到一個合適的狀態,以便為最終調用操作系統內核做好一切准備。
Boot Loader有若干種,其中Grub、Lilo和spfdisk是常見的Loader。
我們以Grub為例來講解吧,畢竟用lilo和spfdisk的人並不多。
早期的操作系統並沒有那麼復雜,當然bootload也沒有那麼多功能,但是如今我們的操作系統越來越復雜,bootload也越來越龐大,而且如今在一台電腦上安裝多系統變得那麼平常,因此之前簡單的bootload已經無法滿足這些功能。
BIOS和MBR都是硬件本身會支持的功能,至於Boot Loader則是操作系統安裝在MBR上面的一套軟件。由於MBR僅有446bytes而已,因此這個引導加載程序是非常小而完美的。這個BootLoader的主要任務如下
提供菜單:用戶可以選擇不同的開機選項,這也是多重引導的重要功能
載入內核文件: 直接指向可開機的程序段來開始操作系統。
轉交其他Loader:將引導加載功能轉交給其他loader負責
上面的前兩點還容易理解,但是第三點很有趣!那表示你的計算機系統裡面可以具有兩個以上的引導加載程序呢。有可能嗎?我們的硬盤不是只有一個MBR而已?但是引導加載程序除了可以安裝在MBR之外,還可以安裝在每個分區的引導扇區。
舉一個例子來說,假設你的個人計算機只有一塊硬盤,裡面分成4個分區。其中第一,二分區分別安裝了Windows及Linux,你要如何在開機的時候選擇用Windows還是Linux開機呢?假設MBR內安裝的是可以同時識別Windows和Linux操作系統的引導加載程序,那麼整個流程如下
做個總結就是這樣:
每個分區都有自己的啟動扇區
系統分區為第一及第二分區
實際可開機的內核文件是放置到各分區內的
loader只會認識自己的系統分區內的可開機內核文件,以及其他的Loader而已
loader可直接指向或者是間接將管理權交給另一個管理程序
現在想一下,為什麼人家常說:”如果要安裝多重引導,最好先安裝Windows再安裝Linux呢“?
這是因為Linux在安裝時,你可以選擇將引導加載程序安裝在MBR或個別分區的啟動扇區,而且Linux的Loader可以手動設置菜單,所以你可以在Linux的Boot Loader裡面加入Windows開機選項
Windows在安裝的時候,他的安裝程序會主動覆蓋掉MBR以及自己所在分區的啟動扇區,你沒有選擇的機會,而且他沒有讓我們自己選擇菜單功能
用戶選擇要加載的內核之後,次引導加載程序(GRUB)就會根據/boot/grub.conf配置文件中所設置的信息,從/boot/所在的分區上讀取Linux內核映像,然後把內核映像加載到內存中並把控制權交給Linux內核。
linux內核獲得控制權之後開始干自己的事
* 檢測硬件
解壓縮自己並安裝必要驅動
初始化與文件系統相關的虛擬設備,LVM或RAID
裝載根文件系統,掛在根目錄下面
完成之後,linux在進程空間裡面加載init程序,下面輪到init干活
根據grub設定的內核映像所在路徑,系統讀取內存映像,並進行解壓縮操作。此時,屏幕一般會輸出“Uncompressing Linux”的提示。當解壓縮內核完成後,屏幕輸出“OK, booting the kernel”。
系統將解壓後的內核放置在內存之中,並調用start_kernel()函數來啟動一系列的初始化函數並初始化各種設備,完成Linux核心環境的建立。至此,Linux內核已經建立起來了,基於Linux的程序應該可以正常運行了。
啟動第五步--用戶層init依據inittab文件來設定運行等級
內核被加載後,第一個運行的程序便是/sbin/init,該文件會讀取/etc/inittab文件,並依據此文件來進行初始化工作。
其實/etc/inittab文件最主要的作用就是設定Linux的運行等級,其設定形式是“:id:5:initdefault:”,這就表明Linux需要運行在等級5上。Linux的運行等級設定如下:
0:關機
1:單用戶模式
2:無網絡支持的多用戶模式
3:有網絡支持的多用戶模式
4:保留,未使用
5:有網絡支持有X-Window支持的多用戶模式
6:重新引導系統,即重啟
關於/etc/inittab文件的學問,其實還有很多
在設定了運行等級後,Linux系統執行的第一個用戶層文件就是/etc/rc.d/rc.sysinit腳本程序,它做的工作非常多,包括設定PATH、設定網絡配置(/etc/sysconfig/network)、啟動swap分區、設定/proc等等。如果你有興趣,可以到/etc/rc.d中查看一下rc.sysinit文件,裡面的腳本夠你看幾天的
具體是依據/etc/modules.conf文件或/etc/modules.d目錄下的文件來裝載內核模塊。
根據運行級別的不同,系統會運行rc0.d到rc6.d中的相應的腳本程序,來完成相應的初始化工作和啟動相應的服務。
你如果打開了此文件,裡面有一句話,讀過之後,你就會對此命令的作用一目了然:
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don’t
# want to do the full Sys V style init stuff.
rc.local就是在一切初始化工作後,Linux留給用戶進行個性化的地方。你可以把你想設置和啟動的東西放到這裡。
執行/bin/login程序,進入登錄狀態
此時,系統已經進入到了等待用戶輸入username和password的時候了,你已經可以用自己的帳號登入系統了。:)