使用U盤自制Linux操作系統

章節導航:

  • 前言

  • Linux系統啓動流程

  • 實驗前的準備

  • 實驗過程

  • 拷貝命令腳本

 

一、前言

我們生活中離不開電腦,時時刻刻在跟操作系統打交道,有時候會被系統中出現的錯誤搞得頭昏腦脹,使用操作系統,不如親自動手組建一個自己的簡單的系統,體驗一下製作操作系統的樂趣。在系統的學習了Linux操作系統之後,就有了理論基礎,所以,迫不及待的想做一個自己的簡單的Linux小系統,有興趣的同學也可以來動手做一做。

在接下來的文章中,小編會先從Linux系統的啓動流程入手,將啓動過程一一展示出來,再進行實驗指導。

二、Linux系統啓動流程

1、加電自檢(POSTpower on system test

這些自檢的功能是有一個軟件程序來實現的,這個軟件程序叫做:BIOSBIOS是基本輸入輸出系統,他是裝在一個硬件芯片CMOS之上,加電過程給CMOS通電,BIOS會根據CMOS上的一些配置信息去讀取硬件的狀態,之後進行硬件設備的初始化。

加電自檢主要是檢測一下硬件設備是夠存在並能夠正常運行,如:CPU、內存、硬盤是否存在並能正常運行,CPU風扇是否能夠運轉散熱,以及一些外圍的輸入輸出設備是否存在,但是有些設備存在與否不影響系統的正常啓動,如鍵盤、鼠標。

2、加載MBR

在硬件初始化之後,BIOS會列出一些可以啓動的裝置順序,接下來就開始讀取第一個可以啓動的設備中操作系統的核心文件。我們必須以一個啓動管理程序來處理這些核心文件的加載問題,這個啓動管理程序爲:BootloaderBoot loader是一個程序,他肯定依賴於一個硬件之上,這個硬件就是硬盤,準確的說是第一個可以啓動的硬盤的第一個扇區內,就是我們之前讀到的MBR(主引導記錄)當中。所以,在加電自檢之後BIOS會將系統引導到MBR中,找到Boot loader

3Boot loader

Boot Loader就是在操作系統內核運行之前運行的一段小程序。通過這段小程序,可以初始化硬件設備,建立內存空間的映射圖,從而將系統的軟硬件環境爲最終調用操作系統內核做好準備。Boot Loader使用最廣的就是Grub了,系統將Linux/boot/grub/grub.conf的配置文件讀取到內存中,根據配置文件中的信息找到內核文件和僞根文件,並將僞根文件加載到內存中,模擬出一個根文件系統,再進行加載內核文件。

4、加載系統內核(Kernel),執行系統初始化信息,

Bootloader可以加載kernelinitrd,然後在內存中讓initrd解壓縮成根目錄,然後內核可以在這個虛擬的根文件系統之上加載合適的驅動程序,來加載硬盤等設備,之後釋放虛擬的根文件系統,並以只讀的方式掛載磁盤上真實的根文件系統,之後就開始正常的啓動過程。此時內核程序已經完全接管了BIOS工作,之後的操作都是有內核來完成的

5、啓動用戶空間第一個執行程序/sbin/init

在內核、硬件及驅動信息加載完畢後,內核會呼叫用戶空間的第一個執行程序/sbin/initinti進程主要功能是準備軟件運行環境,包括系統的主機名稱、網絡配置、文件系統格式、服務運行級別等其他服務的啓動管理。這些所有的操作都是通過init的配置文件來定義的。

Init的配置文件:

Centos5:由於centos5採用的是Sys init方式,其特點是啓動用戶空間的服務程序,通常通過腳本運行,有依賴關係的服務將被串行啓動,這也就導致了centos5的系統啓動過程非常的緩慢,配置文件爲:/etc/initab

Centos6:採用Upstart的方式,其特點是守護進程間的通信依賴於D-Bus進行,因此,可基本實現類似並行啓動:配置文件:/etc/inittab,/etc/init/*.conf

Centos7採用Systemd方式,其特點是服務只有在第一次被訪問到時纔會真正啓動起來,因此Centos7系統的啓動過程非常之快,配置文件是:/usr/lin/system/*

6init程序執行完inittab配置文件後,執行系統初始化腳本rc.sysinit

在定義完運行級別後,Linux系統執行的第一個用戶層文件就是rc.sysinit腳本程序,這個腳本爲初始化用戶空間環境,會執行許多系統初始化任務;在完成系統初始化腳本後,系統還會啓動對應級別下設定爲要啓動的服務,關閉那些設定爲要關閉的服務。該步驟是根據inittab配置文件中定義的運行級別,來運行對應運行目錄中的服務設定腳本。

在服務啓動的最後,會執行最後一個腳本:/etc/rc.d/rc.local,這個腳本是留個用戶的,可以將用戶想要啓動的東西放到這裏。

7、執行/bin/login程序,進入登錄等待狀態

此時就進入了輸入usernamepassword時刻了,漫漫開機之路就算到此結束了。

 

附上啓動流程圖:

wKioL1nDyOXTGi6sAAD0v-un678125.png


三、實驗前的準備

我們要製作的是U盤Linux系統,所以要準備一個U盤,不需要太大夠用就行。

需要準備的工具:U盤、虛擬機或Centos的主機一臺、Centos6系統。

U盤的要求:一般Linux系統不識別NTFS的文件系統,所以要是U盤是NTFS的系統,我們需要將其格式化爲FAT32文件系統的格式,這樣系統才能識別。


四、實驗過程

1、啓動虛擬機的VMware USB Arbitration Service服務

我們需要虛擬機能夠識別USB接口上的U盤,所以要開啓這個服務,如果一斤開啓了,可以直接跳過步驟,小編將爲大家演示如何開啓該服務。

如圖所示:


       右擊我的電腦,打開管理,進入:

        

wKiom1nDyTXCATCmAAEYZM1vrR0691.png

wKiom1nDyTWwNrkiAAFfveNLEdk351.png


在服務中找到VMware USB Arbitration Service項,將服務啓動起來,這個時候重新打開虛擬機。


2、將U盤掛載到虛擬機中的系統上

打開虛擬機後,將右下方顯示的磁盤標誌,找到自己的U盤,選擇連接:

 

wKioL1nDydnir-usAAOqjz7I1Ug017.png

wKiom1nDyhCCAc1oAAF3B-gRfv4995.png

 

3、  U盤進行分區

我們需要將U盤分爲兩個分區,一個用來當做boot分區,一個用來當做根分區。使用:fdisk 命令。

在小編的電腦上識別到的U盤爲/dev/sdc盤號,所以執行:fdisk/dev/sdc,將/dev/sdc1作爲boot分區,分出大小1G;將/dev/sdc2作爲根分區,將剩餘空間全部分給根分區。

 

wKioL1nDyfqjZvQFAAAu0ep0T7M142.png

wKioL1nDyfrRys7tAACF6Et9RiE708.png

wKiom1nDyjDh-DwBAACQF5o29OM508.png

wKiom1nDyjHjO3bmAACTpPUsPhg495.png

 

4、  將分區格式化爲ext4文件系統

分好區後並不能直接使用,我們需要將分區格式化後纔可以正常使用,使用命令:mkfs.ext4 /dev/sdc1需要將/dev/sdc1/dev/sdc2兩個分區進行格式化。

wKioL1nDyjSSBEfWAACVak1FFFY406.png

wKiom1nDymqi_uxXAACdUs3FShI841.png

 

5、  創建掛載將要設置爲boot分區的目錄

該目錄必須爲boot,這樣在生成一些數據的時候纔不會亂,因爲我們要將分區/dev/sdc1掛載到命名爲/boot的目錄下,我們需新建目錄,爲了不和本地系統上的boot目錄混淆,小編創建新的目錄:mkdir –p  /linshi/boot  

wKioL1nDylHiiHkGAAASoO3soEo040.png

6、  /dev/sdc1掛載到/linshi/boot目錄上

執行命令:mount  /dev/sdc1 /linshi/boot


wKioL1nDylLhlmWdAABU0m3d9xo980.png


7、  boot分區/dev/sdc1安裝grub

執行命令:grub-install  --root-directory=/linshi   /dev/sdc

wKioL1nDynqAeHMOAABUwwc0nCc522.png

該命令是用來安裝修復grub引導文件的,如果grub目錄中的文件損壞了,可以通過該命令進行恢復。因爲我們要在U盤的boot目錄上安裝grub,所以需要指定一個位置,那就是—root-directory=/linshi,對象爲/dev/sdc

查看/linshi/boot下的目錄樹結構:

wKiom1nDyrHxyUQyAABZsR_Bo2Y393.png


    查看U盤的MBR表:

wKioL1nDynuiOzw_AAEeBIKdNiA120.png

 

8、  將本地的boot下的內核文件和僞根文件拷貝到U盤中的boot下,命令如下:

    cp /boot/vmlinuz-2.6.32-696.e16.x86_64  /linshi/boot/

    cp /boot/initramfs-2.6.32-696.e16.x86-64.img  /linshi/boot/

執行過程如圖所示:

 wKioL1nDyzPhM2zAAAA98LCZJ5k547.png

9、  手動編寫grub.conf配置文件

Vim /mnt/boot/grub/grub.conf

內容如下:

default=0

timeout=5

hiddenmenu

title Centos-jiake

        root(hd0,0)

        kernel/vmlinuz-2.6.32-696.e16.x86_64 root=UUID=U盤的根分區的UUID selinux=0 init=/bin/bash

        initrd/ initramfs-2.6.32-696.e16.x86-64.img

如圖所示:

wKiom1nDy3zCbnY-AABHYXoo_Hk803.png

10、             創建掛載根分區的目錄,並掛載U盤的根分區

    mkdir /linshi/sysroot

    mount /dev/sdc2  /linshi/sysroot

如圖:

wKiom1nDy6DB3vanAACF92ZWb8g264.png

11、             U盤的根分區下創建與本地根下相同的目錄

一個一個創建太慢,我們使用一個快捷的方式,先將本地根下的目錄名全部存放起來,做成一個列表,然後一次性創建。

ls  / >  /mulu.txt

              mkdir –p `cat mulu.txt`

如圖:

wKiom1nDy7LCxqAcAACdyur-usE503.png 

12、             拷貝網卡驅動

有時候我們需要用用網卡,所以我們將網卡驅動一塊拷貝過去,如果不想使用網卡功能,可以不用拷貝這個文件驅動。

使用locate e1000找到網卡驅動的位置,e1000是網卡的驅動程序文件。

如圖所示:

wKioL1nDy46yea_pAADPh-2VjkQ603.png

13、             通過命令拷貝腳本,將需要使用的命令拷貝到U盤的根分區上

這個腳本是小編自己編寫的,如果你不會,不用着急,小編會在後面附上源代碼。如果你要使用腳本,記得給腳本加上執行的權限。具提的操作可以看小編的截圖:

wKiom1nDy9mzDOh6AAF_PIQwjCw274.png

 

14、             查看我們U盤根分區下的樹狀結構圖

我們拷貝完命令,一定要驗證命令是否拷貝成功,並且路徑一定要正確。命令原來在什麼地方,拷貝過來還要放到對應的目錄下。否則會導致命令不可用。 wKioL1nDy6Oh8CeEAABA1gI_27M840.png

 wKiom1nDy9nyEcj5AABVkv7GNkc171.png

 wKioL1nDy6SQYQ5vAABs9RCh1rs206.png

15、             完成命令移植的功能後,將U盤放到獨立的機器上啓動

要關機將U盤拔下來,這裏小編使用電腦作爲整機,從U盤啓動,所以就不能呈上優質的截圖了。一下圖片使用手機拍攝。

對於不同的機型,進入本地BIOS的按鍵也不同,請各位同學自行尋找進入BIOS的按鍵,進入BIOS需要將U盤設爲第一啓動項,(爲了在BIOSboot啓動項顯示出U盤,需要先將U盤插入電腦)



wKioL1nDzFDjHuHWAAvkeGa1Cio832.png


找到自己的U盤,使用shift +將U盤移動到第一位:

 wKiom1nDzIzTmEsyAAy_5CGE4r4849.png

完成後按下F10保存退出啓動:

 wKioL1nDzFjyCMRlAAUE0zZ0OQo252.png

16、             啓動成功!

wKioL1nDzIiwubRQAAve4mFePTw579.png

稍等片刻,我們就能看到成功進入bash的界面了,由於我們自制了一個簡單的Linux系統,所以目前只是使用bash進入了一個簡單的bash環境,可以執行一些簡單的命令,如果想使用init啓動進程,需要配置更多的文件,如果有興趣的同學可以據需深入研究

五、拷貝命令腳本

    #!/bin/bash

    #將用戶指定的命令拷貝到對應的根目錄下

    copy_comd() {

            com_path=`which $1`

            com_dest=`dirname $com_path`

            [ ! -d $dir$com_dest ] && mkdir -p $dir$com_dest

            ls $dir$com_path  &> /dev/null && { echo "該命令已存在!" ;return 99; }

            cp  $com_path $dir"$com_path"

            echo -e "$com_path  \e[33;5m ====>\e[0m  $dir"$com_path""

    }

  

    #將命令所依賴的庫文件拷貝到對應的目錄中

    copy_comfile(){

        ldd $(which $1) |grep -oE "/.* " | while read libfile

        do

            local lib_destdir=$dir$(dirname $libfile)

            local lib_destfile=$dir$libfile


            if [ -e $lib_destfile ];then

                continue

            elif [ -d $lib_destdir ];then

                cp  $libfile $lib_destdir

                echo -e "$libfile  \e[33;5m ===> \e[0m $lib_destfile"     

            else

                mkdir -p $lib_destdir &> /dev/null

                cp  $libfile $lib_destdir 

                echo -e "$libfile  \e[33;5m ===> \e[0m $lib_destfile"

            fi

        done

    }    


   #主程序(需要先指定根目錄,每個執行步驟都可以quit退出。)

    while true;do

    read -p "Please input the dir("quit" to exit!): " dir

    if [ "$dir" == quit ] ;then 

            exit

    fi

    [ -z $dir ] && { echo -e "\e[31m Please input the dir!\e[0m";continue;}|| break

    done

    ls -d $dir &> /dev/null || mkdir -p $dir

    while true; do

        read -p "Please input the command that you want to copy("quit" to exit! ): " com 

    if [ "$com" == quit ]; then

        exit

    fi

        which "$com" &> /dev/null || { echo "This command is no exited!" ;continue; }

    copy_comd $com

    ret=$?

    [ $ret -eq 99 ] && continue 

    copy_comfile $com

    done

 #(記得給腳本加執行權限哦!)



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