這幾天對於操作系統是如何引導啟動的特征的感興趣,已經到了不能自拔的狀態了,所以索性好好了解一下;
前面已經說過了,MBR對於系統啟動的重要性,這是不多啰嗦; 現在介紹一個 grub ,啟動管理器,它可以用於引導不同的系統;
grub 是一個怎么樣的引導原理?
通過我的實驗,我得到的結論就是: 整個grub啟動管理器其實也算是有點大的,引導扇區里是放不開的; 所以,grub會往引導扇區(可以是MBR, 也可以是每一個分區里面的引導扇區)里面寫入部分內容,對於剩余的部分,它會寫入到我們的硬盤分區里面的;在啟動時,首先運行引導扇區里的程序, 然后在運行硬盤分區里的程序,最后引導操作系統;
對於引導扇區里的程序是如何找到硬盤分區里的程序與配置的,這個就是細節方面的問題了,我們可以忽略;不過我也是一個好學習的人,我也查了查相關的資料,有的解釋如下:
來自:作者:js li
鏈接:https://www.zhihu.com/question/27652991/answer/37500373
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。grub的話,肯定是要在mbr里寫東西的,但446字節的機器碼也干不了太多東西,只是負責把后續的內容加載到內存在執行而已。這個寫到mbr的是stage1,它加載的是寫在mbr之后62個扇區中的stage1.5(因為過去磁盤是按磁道還划分分區的,一個碰道63個扇區,因為mbr占據了第一個磁道的第一個扇區,所以第一個分區只能從第二個磁道開始,這樣在mbr和第一個分區之間就留下了62個扇區的空間,62*512byte=31KB)。
mbr之前說了容量太小沒法放下識別文件系統的代碼,只能以計算扇區絕對偏移的方法加載stage1.5,但31KB的stage1.5就足夠了(但基本也只夠一種類型的文件系統,所以stage1.5是有好幾個,分別對應ext4,xfs等等,在grub安裝時根據需要寫入,隨便一提,正是因為GPT分區表占用了后62個扇區的相當一部分位置,導致空間不夠寫下stage1.5,所以需要額外分出一個非常小的分區來存放)。 (我的備注:我在寫grub時,沒有設置是ext4,還是xfs, 應該是它自動識別的吧)
stage1.5可以識別文件系統,然后根據安裝時硬寫到里面的系統路徑(hexdump可以看到)找到stage2,然后這個stage2才是真正負責干活的,它會讀取grub.cfg並生成啟動菜單,然后根據你的選擇加載內核並把執行權限轉過去,完成啟動。
實驗部分:
先跟着實驗走一遍,然后就會更容易明白grub是如何引導的,來,先折騰起來:
我使用的grub版本分別為 grub-0.97 和 grub-2.02;
grub-0.97 的使用:
第一步:我們下載 grub-0.97這個工具,並安裝到 linux系統上
(注意:這里說的安裝是指的 把這個 grub-0.97 工具安裝到 linux 上,而不是把 grub-0.97的啟動管理器安裝到 硬盤分區上;我們需要使用grub-0.97 這個工具來安裝 grub-0.97 啟動管理器)
方法1:在 linux 上 使用 apt-get install grub 下載下來的為就是 grub-0.97版本的,所以直接 apt-get install grub 就下載下來了;
方法2:當然也可以下載源碼,自己編譯(下載地址:ftp://alpha.gnu.org/gnu/grub/):別忘了給 root 權限:
// 假設應該下載完畢,,位置目錄 grub 下: tar xzvf grub-0.97.tar,gz ./configure --prefix=/usr // prefix 指定了安裝的位置,當然也可以放在其它地方,不過需要添加一下環境變量, // 如果不過添加環境變量,就到安裝的目錄下去運行也可以; make make install
第二步:安裝grub 引導管理器到硬盤分區:
方法1:是通過命令一步步的安裝,輸入 grub 會出來 grub的交互窗口如下圖,這時可以輸入命令進行安裝; 至於命令吧,我沒有研究啊,用第二個方法方便;
方法2: 用自帶的 grub-install 腳本安裝: 這個腳本其實也是調用 grub 的命令進行安裝的:
首先 使用help 來看看grub的用法,輸入 grub-install –help:
所以,我們知道了 grub-install 的用法啦.我們僅僅使用下面的命令格式就可以了,其它的就不用管了:
sudo grub-install --root-directory=DIR install_device // DIR指的是grub的安裝到硬盤的那一部分的目錄位置;其實這個不重要,寫到哪里都可以,反正 grub 的第一部分都可以找到的;只要你記住就可以了,因為可以在里面加入配置文件的;
// 不過有一點要求:那就是把交叉硬盤,即不能把grub的第一部分與第二部分寫在不同的硬盤上,我試過,會報錯的;
// install_device 表示了安裝到引導扇區的那一部分的到底的安裝到哪一個引導扇區; // 例如:一塊硬盤為sda, 如果 install_device 為 /dev/sda,則表示安裝到了這個硬盤的MBR上; // 如果 install_device 為 /dev/sda1,則表示安裝到了這個硬盤的第一個主分區的引導扇區上; // 當然如果安裝到第MBR上, grub啟動管理器可以正常運行,如果安裝到分區的引導扇區上,則需要使用到 chainloader(下面會說到)
安裝完成以后,我們在 sdb1的分區下面應有了一個 /boot/grub/ 目錄了;里面有相關的內容;
舉個兩個例子:
我給虛擬機加了一塊硬盤sdb,並且已經分區、格式化完成了,如下:
例子1:把 grub的 引導程序的第一部分寫到硬盤的MBR上, 至於grub的剩余部分安裝到哪,都行,我就安裝到第一個分區里吧,過程如下:(我要先創建一個空目錄 sdb1,然后把硬盤的第一個分區掛載到上面)
這時,開機把啟動項選擇從硬盤 sdb啟動, 就會出現 grub> 窗口了,如下:(由於sdb硬盤上 grub,並沒有配置信息: menu.lst,所以它自己找不到sda硬盤上的系統上,所以需要進行手動引導,見下面)
例子2:把 grub的 引導程序的第一部分寫到硬盤第一分區的引導扇區上, 至於grub的剩余部分同樣的安裝到哪,都行,我就安裝到第一個分區里吧,過程如下:(我要先創建一個空目錄 sdb1,然后把硬盤的第一個分區掛載到上面)
方法與上面相同:只需要把sdb 改為 sdb1就可以了;
補充:(這一小段來自:http://blog.csdn.net/zzqhost/article/details/5935317)
grub-install 是一個腳本,它完成以下任務:
* 調用 grub-mkdevicemap 創建設備映像文件 /boot/grub/device.map
* 復制 *.mod *.lst *.img 文件到 /boot/grub/
* 調用 grub-probe 自動偵測文件系統類型
* 調用 grub-mkimage 生成grub2內核文件 /boot/grub/core.img
* 調用 grub-setup 安裝引導記錄到mbr或分區-
第三步:grub> 命令窗口下如何手動啟動 linux 系統:
由於sdb硬盤上 grub,並沒有配置信息: menu.lst,所以它自己找不到sda硬盤上的系統上,所以進行手動引導:
說明: 1.在 grub-0.97中,會把硬盤識別為 hd0,hd1,hd2, ……; 分區也是從0標志開始的,如第一分區(hd0,0), 第二分區(hd0,1),……;
2. grub 會把啟動盤作為 hd0盤,其它盤為hd1, hd2等;
3. 記得用 tab 補全;
命令如下:
解釋: 1. 第一行 root (hd1,0), 表示設置一個 linux 系統的 /boot 目錄的分區,在這個 /boot 目錄下有 內核文件與啟動的鏡像文件;又由於 這個分區是 grub 看到的,所以用grub的格式表示,那為什么為(dh1,0)呢??因為現在的啟動盤為 sdb,而linux的系統在sda的第一個分區上,所以為(dh1,0); 如果省略這個 root (hd1,0) 也可以,后面找內核與鏡像文件時再指明也行,只是會麻煩一些;
2. 第二行的命令是加核 linux 的內核文件, 對於后面的 root=/dev/sda1是什么?? 它指明了 linux 系統的 / 目錄所在的分區,因為需要把很多東西mount到 / 目錄下的目錄名字下; 這個分區的路徑是 linux 系統看到的,所以為 /dev/sda1;
3. 加載映像文件;(什么是initrd.img,百度或google)
4. 啟動;
第四步: 配置 grub-0.97的配置文件,讓它自動引導:
在 grub-0.97的 配置文件名字為:menu.lst 文件;至於配置文件的內容的書寫方式,不多說,網上有很多,再說 現在都用grub2了,它的配置文件變了,所以研究也沒有用了;我怎么做的呢?我先用 linux 上的grub-0.97 來自動自成一下 配置文件(命令:udpdate-grub),然后把它復制到 sdb1下的 /boot/grub/ 目錄下(這個是我們上面生成的), 然后修改一下: 添加了一行命令: root (hd1,0) :
修改前:
修改后:
此時,我們重新從 硬盤 sdb里啟動電腦,就可以啟動了:
完成;
grub-2.02 的使用:
整個過程與grub-0.97 是相同的,說說不一樣的地方 :
1. grub-2.02 可以在這里下載:ftp://ftp.gnu.org/gnu/grub/ 或 ftp://alpha.gnu.org/gnu/grub/;
或者: ap-get install grub2-common;
2. grub-2.02支持更多的命令;
3. grub-2.02的 grub-install 的參數不一樣了,同樣可以通過 grub-install –help查看,部分如下:
在使用時,這么用:
sudo grub-install --boot-directory=DIR install_device // 例如: sudo grub-install --boot-directory=/sdb1/ /dev/sdb // 它指的是 boot的目錄 , 而不是root的目錄了;
4. 在 grub-2.02中,會把硬盤識別為 hd0,hd1,hd2, ……; 而分區也是從msdos1標志開始的,如第一分區(hd0,msdos1), 第二分區(hd0,msdos2),……;
5. 在grub-2.02中的配置文件變成了 grub.cfg;
6. 當我把 grub-2.02安裝到 sdb的MBR時, 把 linux系統下的 grub.cfg 文件復制到 sdb1分區上的 /grub/ 目錄下時, 修改如下:
把 grub.cfg 里面的 hd0 全部替換為 hd1; 最后,在sdb硬盤啟動時, sda上的 linux 系統啟動成功;
7. 我發現使用在grub-2.02里,使用grub-install 寫入到分區的引導記錄時,會出問題,而使用grub-0.97則不會再現問題;
8.grub-2.02的命令有所不同:
set root=(hd1,msdos1) linux /boot/ vm**** boot=/dev/sda1 initrd /boot/initrd.img*** boot
當把grub 沒有安裝到硬盤的 MBR里面,而是安裝到了 第一分區,或第二分區時,怎么辦?
使用 chainloader 命令( 它屬於 grub的命令),它可以調用另一個啟動器,如:在grub中,輸入命令例如:
root (hd0, 0) // 為安裝grub 的分區,這是為第一分區;
chainloader +1 // 將指定的文件作為一個鏈式裝載程序載入。為了獲取在一個指定分區第一 扇區內的文件,使用+1作為文件名。
boot
這時,就會從硬盤的第一分區進行啟動了;
完;
另外:可以看看相關的:GRUB(簡體中文);