本實驗以centos6為例
系統啟動流程說明
-->加載BIOS,通過BIOS程式加載CMOS的資訊,并通過CMOS獲得硬體資訊
-->開機自檢POST
-->讀取MBR的資訊
-->grub引導系統啟動
-->開啟系統第一個程序init
-->使用者登陸
有幾點我們需要了解:
1、MBR是磁盤的第一個扇區,512位元組,其中前446位元組是boot loader引導加載程式,後64位元組是分區表,最後2位元組是MBR的結束位55aa
系統要啟動,就要加載核心、各種驅動,那linux的核心存放在/boot下,驅動檔案存放在/lib/modules下,是以啟動流程第一步得先進入/boot加載核心檔案,
而/boot是一個單獨的分區并使用ext4檔案系統。也就是說要進入/boot加載核心得先有檔案系統驅動,而要安裝檔案系統驅動得先加載核心。如此進入一個死循環。
但是我們知道,實際情況是linux可以正常啟動的,這是什麼原因呢?
因為有MBR,MBR中前446位元組的boot loader起引導作用,我們稱為grub stage1,接着進入stage1.5階段,此階段加載的資訊在MBR512位元組之後的27個扇區。
stage1.5結束後進入stage2階段,stage2階段會執行配置檔案grub.conf,這份檔案内容如下:
default=0 //預設加載的核心、initrd檔案,0表示第一個title
timeout=5 //開機過程中出現的菜單選項逾時時間
splashp_w_picpath=(hd0,0)/grub/splash.xpm.gz //啟動菜單選項的背景圖檔
hiddenmenu //隐藏菜單的背景執行過程
title CentOS 6 (2.6.32-696.el6.x86_64) //名字而已
root (hd0,0) //以第1塊磁盤的第1個分區為根,說白了就是/boot為根,此處的根為系統啟動使用,與啟動後的根/兩碼事
kernel /vmlinuz-2.6.32-696.el6.x86_64 ro root=UUID=f1d8d9f5-4d1a-42e8-8a7f-600f668ce44f rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
//kernel 以隻讀方式加載核心,此處的UUID是啟動結束後的根/的UUID
initrd /initramfs-2.6.32-696.el6.x86_64.img
//initrd 其中含有檔案系統驅動,這樣就可以加載核心檔案了
2、啟動系統第一個程序/sbin/init,其作用就是部署好軟體環境,即主機名稱、網絡配置、檔案系統格式等
而實作這些功能,主要是由/etc/inittab和/etc/init.d/*.conf這些檔案完成的(centos6版本)。centos5版本的這些功能全在/etcinittab這一個檔案上。
其大緻含義如下:
-->預設的runlevel,使用者登陸系統預設的級别
- 0:關機
- 1:單使用者模式
- 2:多使用者模式,有些網絡功能不支援
- 3:完全多使用者模式,字元界面
- 4:預留
- 5:圖形界面(預設runlevel)
- 6:重新開機
-->執行系統軟體運作環境的腳本/etc/rc.d/rc.sysinit
其作用就是準備好系統的運作環境,如挂載檔案系統、swap、時鐘、加載外設驅動、激活sysctl.conf檔案設定核心參數
-->7個不同runlevel,啟動可非啟動服務腳本的路徑
-->斷電和恢複供電的處理
-->終端tty的設定
-->界面運作設定
這些步驟完成了,使用者就可以登陸使用系統了;
我們做個實驗,加深下了解
自制linux系統
準備:一塊新的磁盤、一台裝好系統的機器和一台沒有系統的機器。可以在虛拟機上完成本實驗
步驟1、在本機對新磁盤建分區、檔案系統
建立2個必要的分區 /dev/sdb1對應boot,/dev/sdb2對應/
fdisk /dev/sdb
建立檔案系統,以ext4為例
mkfs.ext4 /dev/sdb1
mkfs.ext4 /dev/sdb2
blkid 指令可以檢查檔案系統資訊
步驟2、挂載boot
mkdir /mnt/boot
挂載目錄必須為boot,因為grub的stage2會專門找到boot目錄
mount /dev/sdb1 /mnt/boot/
步驟3、安裝grub
grub-install --root-directory=/mnt /dev/sdb
stage1安裝在/dev/sdb磁盤上,stage2安裝在/mnt/boot目錄下
此時/mnt/boot裡面會有用于grub的stage2階段的目錄
步驟4、複制核心、initramfs
cp /boot/vmlinuz-2.6.32-696.el6.x86_64 /mnt/boot/
cp /boot/initramfs-2.6.32-696.el6.x86_64.img /mnt/boot/
步驟5、編輯grub.conf

圖中的内容上文基本都介紹過,本實驗中root=/dev/sda2,因為這塊磁盤是要作為另一台機器的啟動磁盤自然是sdba2了
selinux=0,因為selinux可能會影響本實驗效果,是以開始就将其關閉
init=/bin/bash,我們使用bash作為第一個啟動程序
步驟6、挂載根/,并初始化
建立目錄并挂載根
mkdir /mnt/root
mount /dev/sdb2 /mnt/root/
mkdir /mnt/root/{etc,lib,sbin,tmp,var,sys,proc,dev,} //建立root下對應的目錄
運作下述腳本,其作用是複制指令檔案與庫檔案到根目錄下(/mnt/root),前提是需要我們輸入常用的指令
我們輸入的指令就是自制的linux系統支援的指令
#! /bin/bash
title () {
export CMD
read -t 30 -p "input an exec cmd or press 'quit': " CMD
if [ "$CMD" = "quit" ];then
exit
else
is_exec
fi
title
}
#判斷輸入的是可執行檔案
is_exec () {
if `which $CMD &> /dev/null` ;then
copy_cmdfile
copy_libfile
echo "--->done"
else
echo "not a command"
exit
fi
}
#拷貝指令檔案
copy_cmdfile () {
EXEC_CMD=`which $CMD`
if [ ! -e /mnt/root$EXEC_CMD ];then
cp --parents $EXEC_CMD /mnt/root
fi
unset EXEC_CMD
}
#拷貝指令檔案對應的庫檔案
copy_libfile () {
ldd `which $CMD` | grep -o "/.*[0-9] " | while read line ;do
if [ ! -e /mnt/root$line ];then
cp --parents $line /mnt/root/
fi
done
unset line
}
title
至此實驗結束,然後關機,取出磁盤,裝到另一台沒有系統的主機上,啟動即可