天天看點

自制linux系統

本實驗以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

自制linux系統

圖中的内容上文基本都介紹過,本實驗中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      

至此實驗結束,然後關機,取出磁盤,裝到另一台沒有系統的主機上,啟動即可

繼續閱讀