国产欧美日韩第一页|日本一二三不卡视频|在线精品小视频,亚洲第一免费播放区,metcn人体亚洲一区,亚洲精品午夜视频

計算機是怎樣啟動的

2018-01-07 19:45:01 12030

先問一個問題,”啟動”用英語怎么說?

回答是boot。可是,boot原來的意思是靴子,”啟動”與靴子有什么關(guān)系呢? 原來,這里的boot是bootstrap(鞋帶)的縮寫,它來自一句諺語:

"pull oneself up by one's bootstraps"

字面意思是”拽著鞋帶把自己拉起來”,這當(dāng)然是不可能的事情。最早的時候,工程師們用它來比喻,計算機啟動是一個很矛盾的過程:必須先運行程序,然后計算機才能啟動,但是計算機不啟動就無法運行程序!

早期真的是這樣,必須想盡各種辦法,把一小段程序裝進(jìn)內(nèi)存,然后計算機才能正常運行。所以,工程師們把這個過程叫做”拉鞋帶”,久而久之就簡稱為boot了。

計算機的整個啟動過程分成四個階段。

一、第一階段:BIOS

上個世紀(jì)70年代初,”只讀內(nèi)存”(read-only memory,縮寫為ROM)發(fā)明,開機程序被刷入ROM芯片,計算機通電后,第一件事就是讀取它。

image.png

這塊芯片里的程序叫做”基本輸出輸入系統(tǒng)”(Basic Input/Output System),簡稱為BIOS。

1.1 硬件自檢

BIOS中主要存放的程序包括:自診斷程序(通過讀取CMOS RAM中的內(nèi)容識別硬件配置,并對其進(jìn)行自檢和初始化)、CMOS設(shè)置程序(引導(dǎo)過程中,通過特殊熱鍵啟動,進(jìn)行設(shè)置后,存入CMOS RAM中)、系統(tǒng)自動裝載程序(在系統(tǒng)自檢成功后,將磁盤相對0道0扇區(qū)上的引導(dǎo)程序裝入內(nèi)存使其運行)和主要I/O驅(qū)動程序和中斷服務(wù)(BIOS和硬件直接打交道,需要加載I/O驅(qū)動程序)。

BIOS程序首先檢查,計算機硬件能否滿足運行的基本條件,這叫做”硬件自檢”(Power-On Self-Test),縮寫為POST。

如果硬件出現(xiàn)問題,主板會發(fā)出不同含義的蜂鳴,啟動中止。如果沒有問題,屏幕就會顯示出CPU、內(nèi)存、硬盤等信息。

1.2 啟動順序

硬件自檢完成后,BIOS把控制權(quán)轉(zhuǎn)交給下一階段的啟動程序。

這時,BIOS需要知道,”下一階段的啟動程序”具體存放在哪一個設(shè)備。也就是說,BIOS需要有一個外部儲存設(shè)備的排序,排在前面的設(shè)備就是優(yōu)先轉(zhuǎn)交控制權(quán)的設(shè)備。這種排序叫做”啟動順序”(Boot Sequence)。

打開BIOS的操作界面,里面有一項就是”設(shè)定啟動順序”。

image.png

二、第二階段:主引導(dǎo)記錄

BIOS按照”啟動順序”,把控制權(quán)轉(zhuǎn)交給排在第一位的儲存設(shè)備。即根據(jù)用戶指定的引導(dǎo)順序從軟盤、硬盤或是可移動設(shè)備中讀取啟動設(shè)備的MBR,并放入指定的位置(0x7c000)內(nèi)存中。

這時,計算機讀取該設(shè)備的第一個扇區(qū),也就是讀取最前面的512個字節(jié)。如果這512個字節(jié)的最后兩個字節(jié)是0x55和0xAA,表明這個設(shè)備可以用于啟動;如果不是,表明設(shè)備不能用于啟動,控制權(quán)于是被轉(zhuǎn)交給”啟動順序”中的下一個設(shè)備。

這最前面的512個字節(jié),就叫做”主引導(dǎo)記錄”(Master boot record,縮寫為MBR)。

2.1 主引導(dǎo)記錄的結(jié)構(gòu)

“主引導(dǎo)記錄”只有512個字節(jié),放不了太多東西。它的主要作用是,告訴計算機到硬盤的哪一個位置去找操作系統(tǒng)。

主引導(dǎo)記錄由三個部分組成:

(1) 第1-446字節(jié):調(diào)用操作系統(tǒng)的機器碼。

(2) 第447-510字節(jié):分區(qū)表(Partition table)。

(3) 第511-512字節(jié):主引導(dǎo)記錄簽名(0x55和0xAA)。

其中,第二部分”分區(qū)表”的作用,是將硬盤分成若干個區(qū)。

2.2 分區(qū)表

硬盤分區(qū)有很多好處??紤]到每個區(qū)可以安裝不同的操作系統(tǒng),”主引導(dǎo)記錄”因此必須知道將控制權(quán)轉(zhuǎn)交給哪個區(qū)。

分區(qū)表的長度只有64個字節(jié),里面又分成四項,每項16個字節(jié)。所以,一個硬盤最多只能分四個一級分區(qū),又叫做”主分區(qū)”。

每個主分區(qū)的16個字節(jié),由6個部分組成:

(1) 第1個字節(jié):如果為0x80,就表示該主分區(qū)是激活分區(qū),控制權(quán)要轉(zhuǎn)交給這個分區(qū)。四個主分區(qū)里面只能有一個是激活的。

(2) 第2-4個字節(jié):主分區(qū)第一個扇區(qū)的物理位置(柱面、磁頭、扇區(qū)號等等)。

(3) 第5個字節(jié):主分區(qū)類型。

(4) 第6-8個字節(jié):主分區(qū)最后一個扇區(qū)的物理位置。

(5) 第9-12字節(jié):該主分區(qū)第一個扇區(qū)的邏輯地址。

(6) 第13-16字節(jié):主分區(qū)的扇區(qū)總數(shù)。

最后的四個字節(jié)(”主分區(qū)的扇區(qū)總數(shù)”),決定了這個主分區(qū)的長度。也就是說,一個主分區(qū)的扇區(qū)總數(shù)最多不超過2的32次方。

如果每個扇區(qū)為512個字節(jié),就意味著單個分區(qū)最大不超過2TB。再考慮到扇區(qū)的邏輯地址也是32位,所以單個硬盤可利用的空間最大也不超過2TB。如果想使用更大的硬盤,只有2個方法:一是提高每個扇區(qū)的字節(jié)數(shù),二是增加扇區(qū)總數(shù)。

三、第三階段:硬盤啟動

這時,計算機的控制權(quán)就要轉(zhuǎn)交給硬盤的某個分區(qū)了,這里又分成三種情況。

3.1 情況A:卷引導(dǎo)記錄

上一節(jié)提到,四個主分區(qū)里面,只有一個是激活的。計算機會讀取激活分區(qū)的第一個扇區(qū),叫做”卷引導(dǎo)記錄”(Volume boot record,縮寫為VBR)。

“卷引導(dǎo)記錄”的主要作用是,告訴計算機,操作系統(tǒng)在這個分區(qū)里的位置。然后,計算機就會加載操作系統(tǒng)了。

3.2 情況B:擴展分區(qū)和邏輯分區(qū)

隨著硬盤越來越大,四個主分區(qū)已經(jīng)不夠了,需要更多的分區(qū)。但是,分區(qū)表只有四項,因此規(guī)定有且僅有一個區(qū)可以被定義成”擴展分區(qū)”(Extended partition)。

所謂”擴展分區(qū)”,就是指這個區(qū)里面又分成多個區(qū)。這種分區(qū)里面的分區(qū),就叫做”邏輯分區(qū)”(logical partition)。

計算機先讀取擴展分區(qū)的第一個扇區(qū),叫做”擴展引導(dǎo)記錄”(Extended boot record,縮寫為EBR)。它里面也包含一張64字節(jié)的分區(qū)表,但是最多只有兩項(也就是兩個邏輯分區(qū))。

計算機接著讀取第二個邏輯分區(qū)的第一個扇區(qū),再從里面的分區(qū)表中找到第三個邏輯分區(qū)的位置,以此類推,直到某個邏輯分區(qū)的分區(qū)表只包含它自身為止(即只有一個分區(qū)項)。因此,擴展分區(qū)可以包含無數(shù)個邏輯分區(qū)。

但是,似乎很少通過這種方式啟動操作系統(tǒng)。如果操作系統(tǒng)確實安裝在擴展分區(qū),一般采用下一種方式啟動。

3.3 情況C:啟動管理器

在這種情況下,計算機讀取”主引導(dǎo)記錄”前面446字節(jié)的機器碼之后,不再把控制權(quán)轉(zhuǎn)交給某一個分區(qū),而是運行事先安裝的”啟動管理器”(boot loader),由用戶選擇啟動哪一個操作系統(tǒng)。

Linux環(huán)境中,目前最流行的啟動管理器是Grub。

image.png

對于grub而言,在MBR中的446字節(jié)的引導(dǎo)程序?qū)儆贕RUB的開始執(zhí)行程序,通過這段程序,進(jìn)一步執(zhí)行stage1.5或是stage2的執(zhí)行程序,將在下面詳細(xì)介紹執(zhí)行過程。

其中stage1.5或是stage2便屬于階段2引導(dǎo)的過程了,stage2過程也是作為GRUB kernel的核心代碼出現(xiàn)。Stage1.5過程(對于GRUB而言存在stage1.5,GRUB2則不存在)的功能很單一,主要就是為了引導(dǎo)stage2過程服務(wù)。由于stage2過程的代碼存放在文件系統(tǒng)下的boot分區(qū)目錄中,因此stage1.5過程就是需要提供一個文件系統(tǒng)的環(huán)境,而該文件系統(tǒng)環(huán)境需要保證系統(tǒng)可以找到stage2過程的文件,那么stage1.5階段提供的文件系統(tǒng)需要是boot文件系統(tǒng)所對應(yīng)的,這個在執(zhí)行g(shù)rub install過程中就已經(jīng)確定了。stage2過程中,主要會把系統(tǒng)切換到保護模式,設(shè)置好C運行時環(huán)境,找到config文件(事實上就是menulist文件),如果沒有找到就執(zhí)行一個shell,等待用戶的執(zhí)行。然后的工作就變成了輸入命令->解析命令->執(zhí)行命令的循環(huán)中。當(dāng)然該階段引導(dǎo)的最終狀態(tài)就是執(zhí)行boot命令,將內(nèi)核和initrd鏡像加載進(jìn)入內(nèi)存中,進(jìn)而將控制權(quán)轉(zhuǎn)交給內(nèi)核。

四、第四階段:操作系統(tǒng)

控制權(quán)轉(zhuǎn)交給操作系統(tǒng)后,操作系統(tǒng)的內(nèi)核首先被載入內(nèi)存。

以Linux系統(tǒng)為例,先載入/boot目錄下面的kernel。內(nèi)核加載成功后,第一個運行的程序是/sbin/init。它根據(jù)配置文件(Debian系統(tǒng)是/etc/initab)產(chǎn)生init進(jìn)程。這是Linux啟動后的第一個進(jìn)程,pid進(jìn)程編號為1,其他進(jìn)程都是它的后代。

然后,init線程加載系統(tǒng)的各個模塊,比如窗口程序和網(wǎng)絡(luò)程序,直至執(zhí)行/bin/login程序,跳出登錄界面,等待用戶輸入用戶名和密碼。

至此,全部啟動過程完成。

另外在大磊的博客中還有許多細(xì)節(jié)部分:

BIOS啟動細(xì)節(jié):

a) 按下電源開關(guān),電源就開始向主板和其它設(shè)備供電;當(dāng)芯片組檢測到電源已經(jīng)開始穩(wěn)定供電了(當(dāng)然從不穩(wěn)定到穩(wěn)定的過程只是一瞬間的事情),它便撤去RESET信號(如果是手工按下計算機面板上的Reset按鈕來重啟機器,那么松開該按鈕時芯片組就會撤去RESET信號);CPU馬上就從地址FFFF:0000H 處開始執(zhí)行指令,放在這里的只是一條跳轉(zhuǎn)指令,跳到系統(tǒng)BIOS中真正的啟動代碼處。

b) 系統(tǒng)BIOS的啟動代碼首先進(jìn)行POST(Power-On Self Test,加電后自檢)。POST的主要檢測系統(tǒng)中一些關(guān)鍵設(shè)備是否存在和能否正常工作,例如內(nèi)存和顯卡等設(shè)備;由于POST是最早進(jìn)行的檢測過程,此時顯卡還沒有初始化,如果系統(tǒng)BIOS在進(jìn)行POST的過程中發(fā)現(xiàn)了一些致命錯誤,例如沒有找到內(nèi)存或者內(nèi)存有問題(此時只會檢查640K常規(guī)內(nèi)存),那么系統(tǒng)BIOS就會直接控制喇叭發(fā)聲來報告錯誤,聲音的長短和次數(shù)代表了錯誤的類型;在正常情況下,POST過程進(jìn)行得非常快,幾乎無法感覺到它的存在。POST結(jié)束之后就會調(diào)用其它代碼來進(jìn)行更完整的硬件檢測。

c) 接下來系統(tǒng)BIOS將查找顯卡的BIOS。前面說過,存放顯卡BIOS的ROM芯片的起始地址通常設(shè)在C0000H處,系統(tǒng)BIOS在這個地方找到顯卡BIOS之后就調(diào)用它的初始化代碼,由顯卡BIOS來初始化顯卡。此時多數(shù)顯卡都會在屏幕上顯示出一些初始化信息,介紹生產(chǎn)廠商、圖形芯片類型等內(nèi)容,不過這個畫面幾乎是一閃而過。系統(tǒng)BIOS接著會查找其它設(shè)備的BIOS程序,找到之后同樣要調(diào)用這些BIOS內(nèi)部的初始化代碼來初始化相關(guān)的設(shè)備。

d) 查找完所有其它設(shè)備的BIOS之后,系統(tǒng)BIOS將顯示出它自己的啟動畫面,其中包括有系統(tǒng)BIOS的類型、序列號和版本號等內(nèi)容。

e) 接著系統(tǒng)BIOS將檢測和顯示CPU的類型和工作頻率,測試所有的RAM,并同時在屏幕上顯示內(nèi)存測試的進(jìn)度。可以在CMOS設(shè)置中自行決定使用簡單耗時少或者詳細(xì)耗時多的測試方式。

f) 內(nèi)存測試通過之后,系統(tǒng)BIOS將開始檢測系統(tǒng)中安裝的一些標(biāo)準(zhǔn)硬件設(shè)備,包括硬盤、CD-ROM、串口、并口和軟驅(qū)等設(shè)備,另外絕大多數(shù)較新版本的系統(tǒng)BIOS在這一過程中還要自動檢測和設(shè)置內(nèi)存的定時參數(shù)、硬盤參數(shù)和訪問模式等。

g) 標(biāo)準(zhǔn)設(shè)備檢測完畢后,系統(tǒng)BIOS內(nèi)部支持即插即用的代碼將開始檢測和配置系統(tǒng)中安裝的即插即用設(shè)備。每找到一個設(shè)備之后,系統(tǒng)BIOS都會在屏幕上顯示出設(shè)備的名稱和型號等信息,同時為該設(shè)備分配中斷、DMA通道和I/O端口等資源。

h) 到這一步為止,所有硬件都已經(jīng)檢測配置完畢了,多數(shù)系統(tǒng)BIOS會重新清屏并在屏幕上方顯示出一個表格,其中概略地列出了系統(tǒng)中安裝的各種標(biāo)準(zhǔn)硬件設(shè)備,以及它們使用的資源和一些相關(guān)工作參數(shù)。

i) 接下來系統(tǒng)BIOS將更新ESCD(Extended System Configuration Data,擴展系統(tǒng)配置數(shù)據(jù))。ESCD是系統(tǒng)BIOS用來與操作系統(tǒng)交換硬件配置信息的一種手段,這些數(shù)據(jù)被存放在CMOS(一小塊特殊的RAM,由主板上的電池來供電)之中。通常ESCD數(shù)據(jù)只在系統(tǒng)硬件配置發(fā)生改變后才會更新,所以不是每次啟動機器時都能夠看到“Update ESCD… Success”這樣的信息。不過,某些主板的系統(tǒng)BIOS在保存ESCD數(shù)據(jù)時使用了與Windows 9x不相同的數(shù)據(jù)格式,于是Windows 9x在它自己的啟動過程中會把ESCD數(shù)據(jù)修改成自己的格式。但在下一次啟動機器時,即使硬件配置沒有發(fā)生改變,系統(tǒng)BIOS也會把ESCD的數(shù)據(jù)格式改回來。如此循環(huán),將會導(dǎo)致在每次啟動機器時,系統(tǒng)BIOS都要更新一遍ESCD,這就是為什么有些機器在每次啟動時都會顯示出相關(guān)信息的原因。

j) ESCD更新完畢后,系統(tǒng)BIOS的啟動代碼將進(jìn)行它的最后一項工作:即根據(jù)用戶指定的啟動順序從軟盤、硬盤或光驅(qū)啟動MBR。在這個過程中會按照啟動順序順序比較其放置MBR的位置的結(jié)尾兩位是否為0xAA55,通過這種方式判斷從哪個引導(dǎo)設(shè)備進(jìn)行引導(dǎo)。在確定之后,將該引導(dǎo)設(shè)備的MBR內(nèi)容讀入到0x7C00[1]的位置,并再次判斷其最后兩位,當(dāng)檢測正確之后,進(jìn)行階段1的引導(dǎo)。

EFI啟動細(xì)節(jié)

 

與傳統(tǒng)MBR相比,GPT采用了不同的分區(qū)方式。

對于傳統(tǒng)MBR,其結(jié)構(gòu)主要如下:

image.png

上圖即對上文中所述的很形象的說明,在圖中看到MBR被分成三個部分,分別是:Bootloader、分別表以及Magic Number。其中Bootloader部分為stage1中被執(zhí)行的起始部分。

相反,對于EFI系統(tǒng)中所采用的GPT分區(qū)方式,則采用了不同于MBR分區(qū)方式的形式,從下圖中可以發(fā)現(xiàn):

image.png

如上圖所示,GPT分區(qū)表主要包括:保護MBR、首要GPT頭、首要GPT、備用GPT、備用GPT頭和磁盤數(shù)據(jù)區(qū)。保護MBR與正常的MBR區(qū)別不大,主要是分區(qū)表上的不同,在保護MBR中只要一個表示為0xEE的分區(qū),以此來表示這塊硬盤使用GPT分區(qū)表。首要GPT頭包含了眾多信息,具體內(nèi)容如下:

image.png

分區(qū)表頭定義了硬盤的可用空間以及組成分區(qū)表的項的大小和數(shù)量。分區(qū)表頭還記錄了這塊硬盤的GUID,記錄了分區(qū)表頭本身的位置和大?。ㄎ恢每偸窃贚BA1)以及備份分區(qū)表頭和分區(qū)表的位置和大?。ㄔ谟脖P的最后)。它還存儲著它本身和分區(qū)表的CRC32校驗。固件、引導(dǎo)程序和操作系統(tǒng)在啟動時可以根據(jù)這個校驗值來判斷分區(qū)表是否有錯誤,如果出錯了,可以使用軟件從硬盤最后的備份GPT分區(qū)表恢復(fù)整個分區(qū)表,如果備份GPT也校驗錯誤,那么磁盤將不可用,系統(tǒng)拒絕啟動。

接下來主要是128個分區(qū)表項,GPT分區(qū)表使用簡單而直接的方式表示分區(qū)。一個分區(qū)表項的前16字節(jié)是分區(qū)類型GUID。例如,EFI系統(tǒng)分區(qū)的GUID類型是{C12A7328-F81F-11D2-BA4B-00A0C93EC93B} 。接下來的16字節(jié)是該分區(qū)的唯一的GUID(這個指的是該分區(qū)本身,而之前的GUID指的是該分區(qū)的類型)。在接下來是分區(qū)其實和末尾的64位LBA編號,以及分區(qū)的名字和屬性。具體結(jié)構(gòu)如下表:

image.png

MBR引導(dǎo)

接下來開始真正的引導(dǎo)過程了,主要說明GRUP的引導(dǎo)??傮w上GRUB更像是一個mini os,只不過這個mini os的作用只是加載其他的操作系統(tǒng),在GRUB中包括stage1、stage1.5(可選)和stage2,其中stage1和stage1.5屬于boot loader,stage2屬于mini os的內(nèi)核部分。GRUB中stage1過程主要位于MBR的前446字節(jié)中(對于支持GPT分區(qū)的磁盤,同樣有最開始的512字節(jié)作為保護MBR,保護MBR與正常的MBR區(qū)別不大,主要是分區(qū)表上的不同,在保護MBR中只要一個表示為0xEE的分區(qū),以此來表示這塊硬盤使用GPT分區(qū)表,不能識別GPT硬盤的操作系統(tǒng)通常會識別出一個未知類型的分區(qū),并且拒絕對硬盤進(jìn)行操作),之后的64字節(jié)為硬盤的分區(qū)表,最后兩個字節(jié)為MBR結(jié)束標(biāo)志位(0xAA55)。

stage1部分占用了446字節(jié),其代碼文件是源碼目錄下stage1/stage1.S文件,匯編后生成一個512字節(jié)的boot.img,被寫在硬盤的0面0道1扇區(qū)中,作為硬盤的MBR。stage1的工作很簡單,就是加載0面0道2扇區(qū)上的512字節(jié)到0×8000,然后跳轉(zhuǎn)到0×8000執(zhí)行。

在0面0道2扇區(qū)上的512字節(jié)內(nèi)容為stage1/start.S文件匯編后生成。該扇區(qū)上的內(nèi)容的作用是加載stage1.5或是stage2過程,并將控制權(quán)轉(zhuǎn)交。

Grub引導(dǎo)

在start過程將控制權(quán)轉(zhuǎn)交后,接下來就是GRUB的核心過程了。該過程之所以區(qū)分stage1.5和stage2,主要原因是GRUB和GRUB2的區(qū)別。在GRUB2中,將stage1.5過程集成到了stage2的過程中,所以stage1.5過程僅僅是針對GRUB的。下面將會分別介紹兩種GRUB版本的兩種過程。

4.1 GRUB中stage1.5過程

Stage1.5過程很無辜,它的作用很單一,但是非常關(guān)鍵。它的主要功用就是構(gòu)造一個boot分區(qū)系統(tǒng)對應(yīng)的文件系統(tǒng),這樣可以通過文件系統(tǒng)的路徑(/boot/grub/)尋找stage2過程需要的core.img,進(jìn)而加載到內(nèi)存中開始執(zhí)行。

Stage1.5存在于0面0道3扇區(qū)開始的地方,并一直延續(xù)十幾k字節(jié)的區(qū)域,具體的大小與相應(yīng)的文件系統(tǒng)的大小有關(guān)(文中涉及到了0面0道1-3+x扇區(qū),這部分扇區(qū)為保留扇區(qū),BIOS不會放置任何數(shù)據(jù)。正因為如此如果轉(zhuǎn)換到GPT分區(qū)形式,系統(tǒng)將不能被正確引導(dǎo),如上文所示,MBR后面的扇區(qū)都被其他內(nèi)容所占據(jù))。Stage1.5過程被構(gòu)建成多種不同類型,但是功能類似,下面簡單介紹一下基本的stage1.5過程的文件系統(tǒng)。e2fs_stage1_5(針對ext2fs,可引導(dǎo)ext2和ext3文件系統(tǒng))、fat_stage1_5(針對fat文件系統(tǒng),可引導(dǎo)fat32和fat16)、ffs_stage1_5、jfs_stage1_5、minix_stage1_5、reiserfs_stage1_5、vstafs_stage1_5和xfs_stage1_5,這些文件被稱為stage1.5過程,這些文件每個至少都在11k以上。除此之外還有兩個比較特殊的文件,分別為nbgrub和pxegrub,這兩個文件主要是在網(wǎng)絡(luò)引導(dǎo)時使用,只是格式不同而已,他們很類似與stage2,只是需要建立網(wǎng)絡(luò)來獲取配置文件。

由于stage1.5過程中會涉及到多個文件系統(tǒng)對應(yīng)的文件,因此本文中主要以ext2fs為例進(jìn)行說明,其他文件系統(tǒng)與此類似,可以同樣進(jìn)行分析理解。

對于ext2fs文件系統(tǒng),用于生成該文件系統(tǒng)的stage1.5過程文件(e2fs_stage1_5)的代碼為stage2/fsys_ext2fs.c文件。

在stage2/filesys.h文件中定義了每個文件系統(tǒng)對外的接口,用于上層調(diào)用,作為stage2過程尋找核心代碼使用,文件系統(tǒng)一般被定義的接口主要就是三個函數(shù),分別是mount、read和dir函數(shù)。對應(yīng)ext2fs,其定義的函數(shù)為:

1

2

3

4

5

6

7

8

#ifdef   FSYS_EXT2FS

#define   FSYS_EXT2FS_NUM 1

int ext2fs_mount   (void);

int ext2fs_read   (char *buf, int len);

int ext2fs_dir   (char *dirname);

#else

#define   FSYS_EXT2FS_NUM 0

#endif

針對ext2fs有如上的函數(shù)名稱,每個函數(shù)將具體在stage2/fsys_ext2fs.c文件中被定義,這里面沒有包含任何的寫的過程,對于bootloader而言僅僅讀就可以完成任務(wù)了,沒必要對其系統(tǒng)進(jìn)行寫操作。其中ext2fs_mount函數(shù)用于檢查文件系統(tǒng)類型,并將superblock讀入到內(nèi)存中;ext2fs_read函數(shù)和ext2fs_dir函數(shù)用于對文件系統(tǒng)具體的操作。在stage2/fsys_ext2fs.c文件中除了需要對這三個函數(shù)的定義之外,還需要文件系統(tǒng)的屬性的數(shù)據(jù)結(jié)構(gòu)(superblock、inode和group結(jié)構(gòu),這些結(jié)構(gòu)最初被定義在include/linux/ext2_fs.h文件中),通過這些數(shù)據(jù)結(jié)構(gòu)描述一個文件系統(tǒng)。

如果讀者有興趣可以試著創(chuàng)建新的文件系統(tǒng)的支持,可以參照目前存在的一些文件系統(tǒng)的模板(實例)編寫。

4.2 GRUB中stage2過程

GRUB中的核心過程也就是stage2過程了,該過程主要是在文件系統(tǒng)建立以后選擇合適的操作系統(tǒng)進(jìn)行加載并轉(zhuǎn)交控制權(quán),達(dá)到最后引導(dǎo)操作系統(tǒng)的目標(biāo)。由于GRUB屬于multi boot loader,因此在引導(dǎo)的時候要進(jìn)行選擇,選擇哪種操作系統(tǒng)來運行。在GRUB內(nèi)部主要包括兩種方式,首先是從menu.list中讀取顯示到屏幕讓用戶選擇,其次是通過grub-shell中定義的命令手動進(jìn)行啟動。本文將在后面介紹這兩種方式如何運行,接下來先介紹一下stage2的具體的執(zhí)行過程。

在上面一節(jié)中介紹過,stage1.5過程中將boot分區(qū)的文件系統(tǒng)加載了,之后又做了一件事情,就是將控制權(quán)轉(zhuǎn)交給stage2,而stage2入口的地方就是stage2/asm.S文件。Stage2/asm.S文件屬于匯編代碼,主要作用是初始化C語言的運行環(huán)境,為下面執(zhí)行C語言的函數(shù)做好準(zhǔn)備,在準(zhǔn)備好之后,將執(zhí)行init_bios_info(stage2/common.c)函數(shù)。init_bios_info函數(shù)的作用是執(zhí)行一些底層的函數(shù),然后跳轉(zhuǎn)到cmain執(zhí)行,cmain函數(shù)位于stage2/stage2.c文件中。cmain函數(shù)內(nèi)部進(jìn)行一個死循環(huán),在循環(huán)內(nèi)部首先加載配置文件,顯示給用戶,在這同時循環(huán)一個內(nèi)層循環(huán),在內(nèi)層循環(huán)中,獲取配置文件中的命令,并解析執(zhí)行。過程中如果沒有可用的配置文件,那么進(jìn)入命令行模式(enter_cmdline函數(shù)),如果找到可用的menu,那么開始執(zhí)行menu的對應(yīng)的內(nèi)容(run_menu函數(shù))。

對于enter_cmdline(stage2/stage2.c)函數(shù),將調(diào)用find_command(stage2/cmdline.c),進(jìn)而執(zhí)行相應(yīng)命令的函數(shù)。

對于run_menu(stage2/stage2.c)函數(shù),將調(diào)用stage2/cmdline.c文件中的run_script函數(shù),進(jìn)而調(diào)用find_command,執(zhí)行相應(yīng)命令的函數(shù)。

這兩種方式雖然經(jīng)過了不同的過程,對用戶輸入的行為進(jìn)行分析和處理,最終調(diào)用的函數(shù)為find_command,在該函數(shù)中順序循環(huán)比較“輸入”的命令是否與系統(tǒng)內(nèi)部定義的相同,如果相同轉(zhuǎn)到執(zhí)行該函數(shù)。在這個比較的過程中包含了一個全局的數(shù)據(jù)結(jié)構(gòu)為struct builtin(stage2/shared.h),由該數(shù)據(jù)結(jié)構(gòu)組成了一個table類型(stage2/builtins.c),將命令與相對應(yīng)的builtin結(jié)構(gòu)對應(yīng)一起并進(jìn)行串聯(lián)。下面描述一下builtin結(jié)構(gòu)的定義:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

struct builtin {

  /* 命令名稱,重要,是搜索命令時的依據(jù)*/

  char *name;

  /* 命令函數(shù),重要,是搜索匹配后調(diào)用的函數(shù)*/

  int (*func) (char *, int);

  /* 功能標(biāo)示,一般未用到. */

  int flags;

  /* 簡短幫助信息*/

  char *short_doc;

  /* 完整幫助信息*/

  char *long_doc;

};

 

struct builtin   *builtin_table[]


struct builtin *builtin_table[];

有興趣的讀者可以對上面的內(nèi)容進(jìn)行擴展,形成自己的命令,主要在stage2/builtins.c文件中按照預(yù)定的格式更新,并添加到builtin_table中即可。

在上面打開配置文件的過程中,主要是通過一些文件操作函數(shù)(被定義在stage2/disk_io.c中)完成。這些文件操作函數(shù)主要包括:grub_open、grub_read、grub_seek和grub_close等,這些函數(shù)屬于grub對外的上層接口,具體的函數(shù)內(nèi)部將調(diào)用前文中提到的boot分區(qū)對應(yīng)的文件系統(tǒng)的相應(yīng)的函數(shù)完成,這個過程主要是通過回調(diào)函數(shù)來完成。該過程整體思路類似于面向?qū)ο筮^程,通過對象操作具體的函數(shù)。

【摘自網(wǎng)絡(luò)】

提交成功!非常感謝您的反饋,我們會繼續(xù)努力做到更好!

這條文檔是否有幫助解決問題?

非常抱歉未能幫助到您。為了給您提供更好的服務(wù),我們很需要您進(jìn)一步的反饋信息:

在文檔使用中是否遇到以下問題: