我們的計算機(jī)在開機(jī)之前,它是一個純硬件的機(jī)器,但是從按下開機(jī)按鈕的那一刻起,ROM上的固化程序就開始為操作系統(tǒng)這個重要的軟件進(jìn)行初始化工作,初始化工作完成以后,將操作系統(tǒng)內(nèi)核加載到內(nèi)存中,操作系統(tǒng)就會幫助我們管理各種硬件資源,帶給了用戶良好的體驗。我們普通用戶通常都不關(guān)心,在電腦啟動時具體都做了什么,但是作為一個IT行業(yè)的從業(yè)人員或者即將作為一名IT行業(yè)的從業(yè)人員,尤其是作為一個搞技術(shù)開發(fā)的從業(yè)人員,對于計算機(jī)是如何啟動的有必要了解一二。
(1)、純硬件檢測與BIOS初始化階段:
首先,在我們按下開機(jī)按鈕的時候,供電系統(tǒng)向計算機(jī)主板和其他硬件設(shè)備供電。剛開機(jī)時電壓不太穩(wěn)定(但是會快速穩(wěn)定下來),所以計算機(jī)主控芯片組會向CPU發(fā)出并保持一個RESET重置信號,讓CPU自動恢復(fù)到初始狀態(tài),當(dāng)主控芯片組檢測到穩(wěn)定供電后,便撤去RESET信號,此時程序計數(shù)器初始化置為FFFF:0H(硬件芯片初始化地址,和軟件沒關(guān)系),CPU開始從FFFF:0H除執(zhí)行指令,這個地址只有一條指令jmp START,F(xiàn)FFF:0H是BIOS(Basic Input Output System) ROM的起始地址,但不是有效指令開始地址,jmp指令跳轉(zhuǎn)的START是真正進(jìn)行BIOS程序起始地址(如圖)。
(3)、其它設(shè)備檢測更新與CPU控制權(quán)限轉(zhuǎn)交:
在完成BIOS設(shè)置之后,需要進(jìn)行兩步操作,①檢測是否存在即插即用設(shè)備,如果存在則為即插即用設(shè)備分配資源,不存在則直接進(jìn)行系統(tǒng)BIOS清屏;②檢測是否存在硬件設(shè)備的更新,如果存在硬件更新,存放于CMOS之中的系統(tǒng)硬件信息就需要進(jìn)行修改,進(jìn)行ESCD(Extended System Configuration Data)更新(ESCD是系統(tǒng)BIOS與操作系統(tǒng)進(jìn)行硬件配置信息交換的一種手段),更新完畢先要把BIOS提供的中斷例程的入口地址登記在中斷向量表中,然后進(jìn)入指定啟動項(BIOS設(shè)置中設(shè)置的優(yōu)先啟動順序:軟盤、硬盤、U盤或光盤)。
假設(shè)是硬盤啟動,系統(tǒng)BIOS讀取硬盤0盤面0磁道1扇區(qū)的MBR(主引導(dǎo)記錄)到內(nèi)存中指定區(qū)域(具體是BIOS提供的int 19中斷例程加載MBR到RAM的0X00007C00H開始處),設(shè)置程序計數(shù)器到指定區(qū)域(EIP=0X00007C00),然后CPU開始執(zhí)行MBR的指令(即CPU使用權(quán)交由MBR來掌控)。
(4)、MBR的工作:
MBR會先檢查硬盤分區(qū)表,然后根據(jù)硬盤分區(qū)表找到硬盤上的引導(dǎo)分區(qū),將引導(dǎo)分區(qū)的首扇區(qū)(boot loader)內(nèi)容調(diào)入內(nèi)存,boot loader中的ntdlr(Windows引導(dǎo)程序)啟動mini-file system divers以便能識別NEFS和FAT32的文件系統(tǒng)的硬盤分區(qū)?;蛘遟rub(Linux引導(dǎo)程序)啟動vmlinuz-version和initrd-version.img(eg:Centos5.5中的/boot/vmlinuz-2.6.18-194.el5和/boot/initrd-2.6.18-194.el5.img)。便完成MBR的引導(dǎo)過程。
注:/boot/vmlinuz-2.6.18-194.el5 和/boot/initrd-2.6.18-194.el5.img分別是Linux內(nèi)核文件與initrd文件(boot loader initialized RAM disk),具體介紹可參考:Linux2.6 內(nèi)核的 Initrd 機(jī)制解析
在最開始接觸MBR和boot sector、boot loader、grub、ntdlr這些概念的時候,腦子是一片混亂,直到我做了一個實驗(即后面要提到的的三系統(tǒng)引導(dǎo)實驗)之后才徹底搞清楚:
在安裝系統(tǒng)的一個磁盤上有多個分區(qū),第一個分區(qū)是主分區(qū)(從1柱面開始),主分區(qū)之前有一個柱面,其第一個扇區(qū)是MBR(0面0道1扇區(qū)),之后便是各個分區(qū),每個分區(qū)的第一個扇區(qū)都是一個boot sector(存放引導(dǎo)加載程序“boot loader”)。而MBR是0面0道1扇區(qū)即首個boot sector中存放的boot loader,只不過廣義的MBR中不僅僅有引導(dǎo)記錄。在安裝Linux時如果需要為/boot分區(qū)分配一些空間,/boot是用來存放操作系統(tǒng)內(nèi)核的啟動文件與配置文件,而grub是Linux系統(tǒng)的引導(dǎo)程序,在/boot/grub/grub.conf中記錄著grub的基本配置信息。ntldr是windows上的boot loader。
總的來說:
①廣義MBR(512Byte)和boot sector都是一個扇區(qū),boot sector是每個分區(qū)的第一個扇區(qū),而MBR是磁盤的第一個扇區(qū)。
②boot loader和狹義MBR(446Byte)是引導(dǎo)加載程序,負(fù)責(zé)加載系統(tǒng)內(nèi)核、提供引導(dǎo)選項或轉(zhuǎn)交引導(dǎo)權(quán)限給其它boot loader(關(guān)于這三種功能我們稍后一一會遇到)。Linux的grub和Windows的ntldr都是boot loader的具體程序。
關(guān)系如下所示(這是先裝了一個Windows7再裝了一個Redhat后的MBR與boot loader情況,Linux的grub改寫了原本直接引導(dǎo)Windwos的MBR,將Linux的grub寫到了MBR里,所以MBR可以直接引導(dǎo)Linux,當(dāng)然也有可以間接通過/dev/sda3中的grub來引導(dǎo)):
上面已經(jīng)提到了boot loader的三種情況:①直接引導(dǎo)kernel、②轉(zhuǎn)交其它boot loader來引導(dǎo),③提供菜單選項(選擇1還是2,即選擇雙系統(tǒng)的Windows7還是Redhat)。如下圖所示(暫時忽略Centos5.5):
上面所述的過程,在MBR加載的前知識點(即BIOS檢查操作)對于實際應(yīng)用來說,幫助不大(CPU初始化FFFF:0H和BIOS加載MBR的部分還是有用的,只是顯卡、內(nèi)存等檢查現(xiàn)在來說沒有太大實際應(yīng)用),但是從MBR加載之后的信息,對于我們在操作系統(tǒng)安裝,雙系統(tǒng)安裝等方面有極大的指導(dǎo)作用。接著我們來看看一個有趣的實驗:先安裝Win7再安裝Redhat6.4,最后安裝Centos5.5的過程中,MBR以及磁盤分區(qū)情況是如何變化的,并且實現(xiàn)按自己心意來隨意引導(dǎo)的方式。
(1)、只安裝Windows7:
只安裝Windows7時的磁盤情況如下所示:
安裝Windows7時,安裝程序?qū)tldr寫入MBR便開機(jī)時讀取MBR時正確引導(dǎo)Windows的Kernel,在自己的boot sector中也寫入了ntldr(備份)。注意:boot sector所在的分區(qū)是分出來存放系統(tǒng)內(nèi)核程序的,C盤是另外一塊分區(qū)??臻e的分區(qū)可以做D:盤、E:盤,但是我們要安裝多個系統(tǒng),所以就不分非系統(tǒng)盤了。
(2)、安裝Windows7以后安裝Redhat6.4:
這一操作的結(jié)果與我們在上面區(qū)分MBR和boot sector時已經(jīng)分析過了(但是分區(qū)圖不太一樣):原本的MBR中是Windwos的ntldr,安裝Redhat時選擇了用Redhat的grub覆蓋Windwos在MBR上的ntldr,但是Redhat識別出了已經(jīng)有一個操作系統(tǒng)是Windows,所以在安裝grub時增加了loader的菜單選項。grub中將Redhat作為了默認(rèn)引導(dǎo)項,不用去讀自己的boot sector了。實際操作中的分區(qū)與MBR變化如下:
(3)、接著安裝一個Centos5.5:
安裝Centos5.5時,選擇是修改MBR還是不修改,我選的是不修改,所以Centos的grub只寫到了/dev/sda安裝好以后,只有Redhat和Others兩個選項,所以Centos無法啟動。此時的文件分區(qū)情況與MBR如下(MBR沒有Centos的grub信息,所以開機(jī)無法直接引導(dǎo)):
用fdisk -l查看磁盤分區(qū)情況:
那么Centos的grub只寫在/dev/sda7的boot sector中 ,如何啟動Centos?我們可以在MBR的選項菜單中直接按’c’鍵,進(jìn)行g(shù)rub編輯:
編輯如下(編輯完一行回車即可):
root (hd0,6)。其實就是掛載/dev/sda7到/boot,即指定/boot,/vmlinuz-version也就是/boot下的/vmlinuz-version而不是根(/)下的/vmlinuz-version。
kernel /vmlinuz-version root=LABEL=/,只要輸入kernel /vmlinuz然后按Tab鍵就能自動補(bǔ)全版本號加上root=LABEL=/即可,下一行也一樣按Tab即可
initrd /initrd-version.img
以上三行其實就是boot loader做的事情,如Redhat的引導(dǎo)過程如下圖:(因為/dev/sda3的boot sector上存放的是redhat的boot loader,所以root (hd0,2)即掛載redhat的/boot)
這樣做只能每次手動boot,如何才能一勞永逸呢?只要我們在redhat的/boot/grub/grub.conf配置文件中將以上三行加上去即可(相當(dāng)于在菜單項中加了一項):
接著我們做以下變化:
進(jìn)入Redhat6.4中,執(zhí)行grub-install /dev/sda1(注意做備份,由于我是用虛擬機(jī)做的,用快照也可以,但是用備份更方便)將redhat的grub安裝到Windows7的boot sector中去,每次選擇菜單中的Windows7,這樣就能達(dá)到引導(dǎo)權(quán)互相交換的效果,修改方式如下所示(由于Linux能夠識別Windows7的NTFS文件系統(tǒng),所以能夠做這一步,如果不能識別是不存在寫權(quán)限的):
效果如下所示:
要恢復(fù)Windows7原來的引導(dǎo),只需要將備份寫回去即可:
類似的操作可以隨意修改,只要能夠識別對應(yīng)文件系統(tǒng),比如把centos的grub裝到Windows的boot sector中,則選擇Windows7是啟動的是Centos的操作系統(tǒng)。
當(dāng)然也可以在開機(jī)選擇時,按‘c’進(jìn)入grub編輯,如下編輯(不做演示):
grub> rootnoverify(hd0,0)
grub> chainloader +1
grub> boot
//MBR轉(zhuǎn)交boot權(quán)限的便是/dev/sda1的boot loader啟動Windows7grub> rootnoverify(hd0,2)
grub> chainloader +1
grub> boot
//MBR轉(zhuǎn)交boot權(quán)限的便是/dev/sda3的boot loader啟動Redhat6.4grub> rootnoverify(hd0,6)
grub> chainloader +1
grub> boot
//MBR轉(zhuǎn)交boot權(quán)限的便是/dev/sda7的boot loader啟動Centos5.5