grub 引導啓動過程詳解

        機器加電啓動後,BIOS開始檢測系統參數,如內存的大小、日期和時間、磁盤設備以及這些磁盤設備用來引導的順序。通常情況下,BIOS都是被配置成首先檢查軟驅或者光驅(或兩者都檢查),然後再嘗試從硬盤引導。如果在這些可移動的設
備中,沒有找到可引導的介質,那麼BIOS通常是轉向第一塊硬盤最初的幾個扇區,尋找用於裝載操作系統的指令。裝載操作系統的這個程序就是boot loader
    linux裏面的boot loader通常是lilo或者grub,從Red Hat Linux 7.2起,GRUB(GRand Unified Bootloader)取代LILO成爲了默認的啓動裝載程序。那麼啓動的時候grub是如何被載入的呢 ?
    grub有幾個重要的文件,stage1,stage2,有的時候需要stage1.5,這些文件一般都在/boot/grub文件夾下面.grub被載入通常包括以下幾個步驟
1、裝載基本的引導裝載程序(stage1),stage1很小,通常是1024字節。stage1通常位於主引導扇區裏面,對於硬盤就是MBR了,stage1的主要功能就是裝載第二引導程序(stage2)。這主要是歸結於在主引導扇區中沒有足夠的空間用於其他東西了,我用的是grub 0.93(grub --version),stage2文件的大小是 107520 bit。
2、裝載第二引導裝載程序(stage2),這第二引導裝載程序實際上是引出更高級的功能, 以允許用戶裝載入一個特定的操作系統。在GRUB中,這步是讓用戶顯示一個菜單或是輸入命令。由於stage2很大,所以它一般位於文件系統之中(通常是boot所在的根分區)。 上面還提到了stage1.5這個文件,它的作用是什麼呢? 你到/boot/grub目錄下看看,fat_stage1_5(或fat_stage_1.5)、e2fs_stage1_5(或e2fs_stage_1.5)、 xfs_stage1_5(或xfs_stage_1.5)等等。很容易猜想stage1.5和文件系統有關係。有時候基本引導裝載程序(stage1)不能識別stage2所在的文件系統分區,那麼這時候就需要stage1.5來連接stage1和stage2了。因此對於不同的文件系統就會有不同的stage1.5。但是對於grub 0.93好像stage1.5並不是很重要,因爲我試過了,在沒有stage1.5的情況下, 我把stage1安裝在軟盤的引導扇區內,然後把stage2放在格式化成ext2或者fat格式的軟盤內,啓動的時候照常引導,並不需要e2fs_stage1_5或者fat_stage1_5。
下面是我的試驗:
    #mkfs.ext2  /dev/fd0
    #mount -t ext2  /dev/fd0  /mnt/floppy
    #cd  /mnt/floppy
    #mkdir boot
    #cd  boot
    #mkdir grub  (以上三步可用mkdir -p  boot/grub命令完成)
    #cd grub
    #cp  /boot/grub/{stage1,stage2,grub.conf}  ./
    #cd; umount /mnt/floppy
    以上幾步把軟盤格式化成ext2格式,然後把stage1、stage2、grub.conf這幾個啓動的時候必須的文件拷貝到軟盤的指定目錄下。下面安裝grub到軟盤上。
   #grub  (進入grub環境)
   grub> install (fd0)/boot/grub/stage1 (fd0)  (fd0)/boot/grub/stage2 p (fd0)/boot/grub/grub.conf
   以上這條命令也可以用下面的兩句代替
   grub>root (fd0)    #grub的根目錄所在的分區
   grub>setup (fd0)   #這一步就相當於上面的install命令
   我在這裏解釋一下
    install (fd0)/boot/grub/stage1 (fd0)  (fd0)/boot/grub/stage2 p (fd0)/boot/grub/grub.conf 這條命令。
install    告訴GRUB將(fd0)/boot/grub/grub/stage1   安裝到軟驅的引導扇區(fd0),
(fd0)/boot/grub/stage2  告訴grub stage2這個文件所在的位置,
p 參數後面跟着(fd0)/boot/grub/grub.conf 告訴grub的配置文件所在的位置。
    好了,讓BIOS從軟驅啓動,試一下,沒有e2fs_stage_1.5文件照樣能夠進入系統。
其實這就是一個小小的啓動盤啊.。瞭解了grub的運行原理,就簡單多了^_^)
  3、 現在我們已經到grub的開機選單這一步了,接下來grub所需要做的就是裝載在一個特定分區上的操作系統,如linux內核。一旦GRUB從它的命令行或者配置文件中,接到開始操作系統的正確指令,它就尋找必要的引導文件,然後把機器的控制權移交給操作系統。
      一個典型的引導linux的命令如下:
     title 51base
           root(hd0,0)
           kernel /bzImage  ro  root=/dev/ram0
           initrd /initrd.img
     這裏有必要注意一下幾個問題:
     (1)grub的磁盤以及分區的命名方式和linux有所區別。第一個磁盤是從0開始,第一個分區也是從0開始。譬如第一個硬盤的第5分區在linux下面是/dev/hda5,而在grub裏面是(hd0,4)。再如/dev/fd0在grub裏面是(fd0,0)。(最後一句如有錯誤望提醒)
     (2)不管是IDE硬盤hda、hdb還是SCSI硬盤sda、sdb,在grub裏面都是以hd方式命名。譬如虛擬機裏面的/dev/sda2在grub裏面是(hd0,1),/dev/hdb7在grub裏面以(hd1,6)命名。
     (3)要搞清楚上面兩個root的關係,root (hd0,0)中的root是grub命令,它用來指定boot所在的分區作爲grub的根目錄。而root=/dev/ram0是kernel的參數,它告訴操作系統內核加載完畢之後,真實的文件系統所在的設備。要注意grub的根目錄和文件系統的根目錄的區別。
     kernel命令用來指定內核所在的位置,"/"代表(hd0,0),也就是grub的根目錄
     initrd命令用來指定初始化ram的img文件所在位置。
    grub載入內核bzImage並展開到指定位置(應該是0x100000這個地方),同時載入initrd.img到內存(不知道是什麼地方).
ps:
    grub的任務至此就結束了,下面grub將機器的控制權轉交給操作系統(linux)。
   操作系統接到控制權之後,開始start_kernel,接着內核將initrd.img展開到/dev/ram0爲臨時根文件系統,執行裏面的linuxrc文件。
    這裏有必要說一下initrd的作用特別是它裏面的核心文件linuxrc的作用。initrd是inital ram disk的宿寫。
   當存在initrd的時候,機器啓動的過程大概是以下幾個步驟(當initrd這一行用noinitrd 命令代替後,就不存在initrd了)
    1)boot loader(grub)加載內核和initrd.img
    2)內核將壓縮的initrd.img解壓成正常的ram disk並且釋放initrd所佔的內存空間
    3)initrd作爲根目錄以讀寫方式被掛載
    4)initrd裏面的文件linuxrc被執行
    5)linuxrc掛載新的文件系統
    6)linuxrc使用pivot_root系統調用指定新的根目錄並將現有的根目錄place到指定位置
    7)在新的文件系統下正式init
    8)initrd被卸載
    爲了便於理解,我將red hat linnux9 裏面的initrd-2.4.20-8.img拿出來分析一下。
    這其實是一個壓縮了的文件,是以gz結尾的。
[root@localhost root]#cp  /boot/initrd-2.4.20-8.img  /mnt/initrd-2.4.20-8.gz
[root@localhost root]#gunzip /mnt/initrd-2.4.20-8.gz
[root@localhost root]#mount -o loop /mnt/initrd-2.4.20-8  /mnt/ram
[root@localhost root]#cd  /mnt/ram
[root@localhost ram]#ls
bin dev etc lib linuxrc loopfs  proc sbin sysroot
[root@localhost ram]#ls bin
insmod modprobe nash
[root@localhost ram]#ls lib
Buslogic.o  ext3.o  jbd.o  scsi_mod.o   sd_mod.o
[root@localhost ram]ls  dev
console  null  ram  systty  tty1  tty2  tty3  tty4
sbin目錄是指向bin目錄的一個連接,其他目錄是空的.
[root@localhost ram]cat  linuxrc
#!/bin/nash
1.echo "Loading scsi_mod.o module"
2.insmod /lib/scsi_mod.o
3.echo "Loading sd_mod.o module"
4.insmod /lib/sd_mod.o
5.echo "Loading BusLogic.o module"
6.insmod /lib/BusLogic.o
7.echo "Loading jbd.o module"
8.insmod /lib/jbd.o
9.echo "Loading ext3.o module"
10.insmod /lib/ext3.o
11.echo Mounting /proc filesystem
12.mount -t proc /proc /proc
13.echo Creating block devices
14.mkdevices /dev
15.echo Creating root device
16.mkrootdev /dev/root
17.echo 0x0100 > /proc/sys/kernel/real-root-dev
18.echo Mounting root filesystem
19.mount -o defaults --ro -t ext3 /dev/root /sysroot
20.pivot_root /sysroot /sysroot/initrd
21.umount /initrd/proc
上面的編號是爲了下面好說明加上去的。
   1)首先我們必須注意的是這裏使用的shell是nash而不是bash,nash是專門爲linuxrc可執行腳本設計的,因此你有必要看一看nash的man文檔。
1-10行是加載一些必要的模快
11-12行加載proc內核文件系統
13-14行利用nash內建的命令mkdevices創建塊設備,mkdevices是根據/proc/partitions文件創建裏面列出的所有塊設備
15-16行利用nash內建的命令mkrootdev,mkrootdev使它後面的參數/dev/root成爲一個塊節點從而使得根分區設備被掛載,其中根分區設備由grub.conf裏面的kernel命令後面所帶的參數root=決定,如果root=參數沒有被指定,/proc/sys/kernel/real-root-
dev文件將提供根分區設備號
17行將數字256寫入到後面的文件裏面去
18-19行掛載根文件系統到/sysroot目錄下,/dev/root裏面的內容就是root=參數所指定的設備裏面的內容
20行調用pivot_root改變根目錄所在地並place舊的根目錄到指定的位置.21行卸載舊的根目錄裏面的proc內核文件系統.
從這裏面我們總結一下linuxrc的作用:  (參考/usr/src/linux-2.4/Documentation/initrd.txt文檔)
    2)/linuxrc文件決定在掛載真正的文件系統之前所需完成的事情(譬如加載必要的網絡驅動或者加載ext3文件系統).
    3)/linuxrc加載必要的模塊.
    4)/linuxrc掛載根文件系統
    5)/linuxrc調用pivot_root來改變根目錄
    關於initrd的用途可以查考上面提到的文檔,想知道linux系統是如何安裝的嗎?那裏面有答案。
    既然linuxrc的主要目的是加載模快用的,那麼如果我們的內核沒有動態的模塊而所需的功能都是靜態編譯進內核的,那麼是不是可以不用linuxrc文件呢?答案是可以不用,在普通的linux操作系統裏面可以加入noinitrd選項以告知boot loader 不使用initrd。如果我們做網關,因爲ram是我們的文件系統的載體,所以initrd一行當然不能去掉,但是我們可以不用linuxrc文件,sysroot文件夾和initrd文件夾。
    不信的話,試試看吧。
    好了,initrd(linuxrc)已經介紹完了,linuxrc執行完畢之後,系統就會以真正的根目錄正式init。
    系統在/bin/或者/sbin目錄下找到init程式,然後根據它的配置文件/etc/fstab進行初始化,最後調用mingetty程式啓動login完成引導。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章