linux系統啓動流程詳解

一.linux啓動大概流程如下:

    POST --> Boot Sequence(BIOS) --> Boot Loader (MBR) --> Kernel(ramdisk) --> rootfs --> switchroot --> /sbin/init -->(/etc/inittab, /etc/init/*.conf) --> 設定默認運行級別 --> 系統初始化腳本 --> 關閉或啓動對應級別下的服務 --> 啓動終端,流程圖如下:

wKiom1aE17KTQ8xsAANWq_R4oNA991.png

二.詳細剖析過程

1.

POST開機自檢:電腦主機打開電源的時候,隨後會聽到滴的一聲,系統啓動開始了開機自檢
(POST-power on selftest)自檢開始),這個過程中主要是檢測計算機硬件設備比如:
CPU,內存,主板,顯卡,CMOS等設備是否有故障存在,如果有硬件故障的話將按兩種情況
理:對於嚴重故障(致命性故障)則停機,此時由於各種初始化操作還沒完成,不能給出任
何提示或信號;對於非嚴重故障則給出提示或聲音報警信號,等待用戶處理),如果沒有
故障,POST完整自己的接力任務,將尾部工作交接給BIOS處理。

2.

    BIOS:計算機加電自檢完成後第一個讀取的地方就是就是BIOS(基礎輸入輸出系統),BIOS裏面記錄了主機板的芯片集與相關設置,如CPU與接口設備的通信頻率、啓動設備的搜索順序、硬盤的大小與類型、系統時間、外部總線、各種接口設備的I/O地址、已經與CPU通信的IRQ中斷信息,所以,啓動如果要順利啓動,首先要讀取BIOS設置。BIOS此時去讀取硬盤驅動器的第一個扇區(MBR,512字節),然後執行裏面的代碼。

   實際上這裏BIOS並不關心啓動設備第一個扇區中是什麼內容,它只是負責讀取該扇區內容、並執行。此後將系統啓動的控制權移交到MBR部分的代碼,在個人電腦中, Linux的啓動是從0xFFFF0地址開始的。


3.

    Boot Loader 系統引導,我們首先來了解一下MBR,它是Master Boot Record的縮寫。硬盤的0柱面、0磁頭、1扇區稱爲主引導扇區。它由三個部分組成,主引導程序(Bootloader)硬盤分區表DPT(Disk Partition table)和硬盤有效標誌(55AA),其結構圖如下所示:

wKioL1aE4G-SNgU8AABOPhrk2l4392.png

磁盤分區表包含以下三部分:

    1). Partition ID (5:延申 82:Swap 83:Linux 8e:LVM fd:RAID)
    2). Partition起始磁柱
    3). Partition的磁柱數量


4.主引導設備加載Bootloader

    通常情況下,諸如lilo、grub這些常見的引導程序都直接安裝在MBR中。我們以grub爲例來分析這個引導過程。grub引導也分爲兩個階段stage1階段,stage1.5階段和stage2階段;

wKiom1aE4b2RZo8mAADt0NaEP4A521.png由此可見grub目錄下包含了這三個階段的文件,他們各自的作用是什麼呢?

    

    stage1:stage1是直接被寫入到MBR中去的,這樣機器一啓動檢測完硬件後,就將控制權交給了GRUB的代碼。也就是上上圖所看到的前446個字節空間中存放的是stage1的代碼。BIOS將stage1載入內存中0x7c00處並跳轉執行。stage1(/stage1/start.S)的任務非常單純,僅僅是將硬盤0頭0道2扇區讀入內存。此時,stage1是沒有識別文件系統的能力的。

    stage1主要負責BIOS和GRUB之間的交接,載入存放於各個分區中的開機文件。例如Linux下/boot/grub/..下面的一些文件。這部分纔是真正放在MBR中的bootloader。

    stage1文件的大小正好是512字節,事實上stage1文件其實就是MBR中bootloader的備份,而之所以是bootloader而不是MBR, 是因爲這個文件的前446字節纔是和MBR是一樣的。


 

    stage1.5:GRUB開始沒有OS,也沒有文件系統的概念。那麼GRUB是從何時開始有文件系統的功能的呢。這就是stage1.5乾的事情,stage1.5過後,GRUB就能識別文件系統了,就能在磁盤上識別加載文件了怎麼做到的?start.S加載的磁盤上的那些扇區的內容,就是文件系統的代碼,(即start.S的彙編代碼,有興趣的筒子可以去了解一下),將其(大概14個扇區)加載到內存,就具備了操作啓動設備上面文件的功能了,此時文件系統支撐代碼到內存之後,我們在也不需要直接調用INT 13加載扇區內容,我們有了文件系統,我們可以直接操作文件了。那麼/boot/grub/stage2這樣的比較大的文件可以直接操作了。此後grub纔有能力去訪問/boot分區/boot/grub目錄下的 stage2文件,將stage2載入內存並執行。

    Grub的做法是把stage1.5安裝在硬盤最前面的32K,由stage1負責去該區域將stage1.5找出來並執行。

  

    stage2:grub的核心部分,讓用戶以選項的方式將操作系統加載、修改選項以及新增參數,平時開機啓動的時候看到的Grub選項、信息,還有修改GRUB背景等功能都是stage2提供的,stage2會去讀入/boot/grub/grub.conf配置文件。


總結:

    1) BIOS將控制權交給硬盤的主引導區,即MBR。

    2) MBR中的bootloader(stage1)通過內置的地址加載stage1_5;

    3)bootloader通過stage1_5的內容,將分區中的stage2加載;

   4)stage2此時就可以在文件系統中將grub.conf文件加載,讓用戶看到選項界面。


通過下面我們可以看到linux的內核VMLnuz,grub、initrd都在/boot目錄下:

wKiom1aE7miRdAHCAAAQ5dScYbs309.png

再看grub下文件:

wKioL1aE7rjSpal4AAGWEQLIfT8814.png

再看看grub.conf配置文件

wKioL1aE7x2BTktIAAK9BjWgBvs859.png


5.Kernel:當stage2被載入內存執行時,它首先會去解析grub的配置文件/boot/grub/grub.conf,然後加載內核鏡像到內存中,並將控制權轉交給內核.而內核會立即初始化系統中各設備並做相關的配置工作,其中包括CPU、I/O、存儲設備等,並且以讀寫的方式掛載根文件系統(根切換),那麼這裏就出現了一個“先有雞還是先有蛋的文件了”,具體是什麼呢?

    要想訪問真正的根文件系統(rootfs)的話,就必須加載根文件系統中的設備,這時根文件系統又沒有掛載,要掛載根文件系統又得加載根文件系統中的驅動程序,那怎麼辦呢?爲了解決這個問題,這是就用到了initrd文件了。  

在來說下kernel初始化所要工作的內容做下簡單總結:  

          探測硬件->加載驅動(initrd)->掛載根文件系統->rootfs(/sbin/init)


詳細解釋如下:

    Linux的設備驅動程序的加載,有一部分驅動程序直接被編譯進內核鏡像中,另一部分驅動程序則是以模塊的形式放在initrd(ramdisk)中。

    Linux內核需要適應多種不同的硬件架構,但是將所有的硬件驅動編入內核又是不實際的,而且內核也不可能每新出一種硬件結構,就將該硬件的設備驅動寫入內核。實際上Linux的內核鏡像僅是包含了基本的硬件驅動,在系統安裝過程中會檢測系統硬件信息,根據安裝信息和系統硬件信息將一部分設備驅動寫入 initrd 。這樣在以後啓動系統時,一部分設備驅動就放在initrd中來加載。這裏有必 要給大家再多介紹一下initrd這個東東:

    initrd的英文含義是bootloader initialized RAM disk,就是由boot loader初始化的內存盤。在linu2.6內核啓動前,boot loader會將存儲介質中的initrd文件加載到內存,內核啓動時會在訪問真正的根文件系統前先訪問該內存中的initrd文件系統。在boot loader配置了initrd的情況下,內核啓動被分成了兩個階段,第一階段先執行initrd文件系統中的init,完成加載驅動模塊等任務,第二階段纔會執行真正的根文件系統中的/sbin/init進程。


我們看一下initrd下文件:

wKioL1aE8tvCqTq2AAKJaCCxuog128.png



再看其中init腳本的內容:

wKioL1aE9CLjfWqmAAJCY2ymd-U053.pngwKiom1aE9DTSl1aJAAIerdx3yiI556.png

wKioL1aE9IXQcAzRAAJhV9hGEfc928.png

從上面的腳本內容我們可以看到init進程的主要工作:

    

掛載 :將initrd中的/proc, /sys  /dev 掛載到當前的主分區中的相應目錄  

創建目錄:/dev/mapper  

通過mknod完成block or character special files的創建  

相關模塊的掛載  

創建root設備  

掛載 /sysroot  

最後完成根切換


    由上面圖片可知,initrd這樣一個虛擬文件根文件系統,作用就是將kernel和真的根文件系統建立關聯關係,讓kernel去initrd中加載根文件系統所需要的驅動程序,並以讀寫的方式掛載根文件系統,並讓執行用戶當中第一個進程init。


現在再讓我們把這一步跟上一步結合起來總結一下:

      grub的stage2將initrd加載到內存裏,然後將其中的內容釋放到內存中,內核便去執行initrd中的init腳本,這時內核將控制權交給了init文件處理。我們簡單瀏覽一下init腳本的內容,發現它也主要是加載各種存儲介質相關的設備驅動程序。當所需的驅動程序加載完後,會創建一個根設備,然後將根文件系統rootfs以只讀的方式掛載。這一步結束後,釋放未使用的內存,轉換到真正的根文件系統上面去,同時運行/sbin/init程序,執行系統的1號進程。此後系統的控制權就全權交給/sbin/init進程了。

    

 

6.到此爲止,跋涉千山萬水,內核空間的工作終於完成,黎明的曙光就要顯現,下一步就是初始化系統了,內核空間的任務開始向用戶空間轉移。/sbin/init進程是系統其他所有進程的父進程,當它接管了系統的控制權先之後,它首先會去讀取/etc/inittab文件來執行相應的腳本進行系統初始化,如設置鍵盤、字體,裝載模塊,設置網絡等。它分爲以下工作:


現在先讓我們看下/etc/inittab的配置的詳細內容:

wKioL1aE91GwHJ6dAAKps1DfPEk562.png

wKioL1aE93fDZrswAAL-S4nz-Ss809.png

各個級別的定義

默認運行級別 3,5

0:halt            //關機  ,shutdown    

1: single user mode    //單用戶維護模式),root用戶,無須認證;維護模式; 

2:multi user mode, without NFS  //不支持NFS功能 ,會啓動網絡功能,維護模式;

3: multi user mode, text mode     //完全功能模式;文本界面

4:reserved               //系統保留,目前無特別使用目的,但習慣以同3級別功能使用;

5: multi user mode, graphic mode   //圖形化界面,完全功能模式  

6: reboot   //重啓


級別切換:init #

級別查看:who -r | runlevel


/etc/inittab的格式及語法:

    [選項]:[runlevel]:[行爲]:[命令]即:id:runlevels:action:process 

行爲:

    wait:等待切換至此任務所在的級別時執行一次;

    respawn:一旦此任務終止,就自動重新啓動之;

    initdefault:設定默認運行級別;此時,process省略;

    sysinit:設定系統初始化方式,此處一般爲指定/etc/rc.d/rc.sysinit腳本;

    

命令:通常是一些腳本


1) 執行系統初始化腳本(/etc/rc.d/rc.sysinit),對系統進行基本的配置,以讀寫方式掛載根文件系統及其它文件系統,到此係統算是基本運行起來了,後面需要進行運行級別的確定及相應服務的啓動。

我們可以看看inittab內定義的初始化腳本:rc.sysinit  --/etc/rc.d/rc.sysinit

wKiom1aE-pjRkPoSAAE8WQeCBfI422.pngwKiom1aE-sSDWyudAAEQcS5U3mg012.png


如上圖所示:rc.sysinit腳本內定義了一些與系統初始化的定義:

    (1) 設置主機名;

    (2) 設置歡迎信息;

    (3) 激活udev和selinux;

    (4) 掛載/etc/fstab文件中定義的所有文件系統; 

    (5) 檢測根文件系統,並以讀寫方式重新掛載根文件系統; 

    (6) 設置系統時鐘; 

    (7) 根據/etc/sysctl.conf文件來設置內核參數;

    (8) 激活lvm及軟raid設備;

    (9) 激活swap設備;

    (10) 加載額外設備的驅動程序;

    (11) 清理操作; 

   (12)然後根據系統運行級別運行相關的服務腳本:/etc/rc.d/init.d/腳本和/etc/rc.d/rc#d

   當/etc/rc.d/rc.sysinit執行完後,系統就可以順利工作了,只是還需要啓動系統所需要的各種服務,這樣主機纔可以提供相關的網絡和主機功能,因此便會執行下面的腳本。


2) 執行/etc/rc.d/rc腳本。該文件定義了服務啓動的順序是先K後S,而具體的每個運行級別的服務狀態是放在/etc/rc.d/rc*.d(*=0~6)目錄下,所有的文件均是指向/etc/init.d下相應文件的符號鏈接。rc.sysinit通過分析/etc/inittab文件來確定系統的啓動級別,然後纔去執行/etc/rc.d/rc*.d下的文件。

wKiom1aE--Ki_9IbAAER7d2imKo762.png


由上圖可知,

rc0-rc6目錄下腳本:

K*     ##只要是以K開頭的文件均執行stop工作  

S*     ##只要是以S開頭的文件均執行start工作  

0-99  (執行次序,數字越小越先被執行)

用戶自定義開機啓動程序(/etc/rc.d/rc.local),可以根據自己的需求將一些執行命令或是腳本寫到/etc/rc.d/rc.local裏,當開機時,可以自動加載


也就是說,/etc目錄下的init.d、rc、rc*.d、rc.local和rc.sysinit均是指向/etc/rc.d目錄下相應文件和文件夾的符號鏈接。我們以啓動級別3爲例來簡要說明一下。

/etc/rc.d/rc3.d目錄,該目錄下的內容全部都是以 S 或 K 開頭的鏈接文件,都鏈接到"/etc/rc.d/init.d"目錄下的各種shell腳本。S表示的是啓動時需要start的服務內容,K表示關機時需要關閉的服務內容。/etc/rc.d/rc*.d中的系統服務會在系統後臺啓動,如果要對某個運行級別中的服務進行更具體的定製,通過chkconfig命令來操作,或者通過setup、ntsys、system-config-services來進行定製。如果我們需要自己增加啓動的內容,可以在init.d目錄中增加相關的shell腳本,然後在rc*.d目錄中建立鏈接文件指向該shell腳本。這些shell腳本的啓動或結束順序是由S或K字母后面的數字決定,數字越小的腳本越先執行。例如,/etc/rc.d/rc3.d /S01sysstat就比/etc/rc.d/rc3.d /S99local先執行。


3)執行用戶自定義引導程序/etc/rc.d/rc.local。其實當執行/etc/rc.d/rc3.d/S99local時,它就是在執行/etc/rc.d/rc.local。S99local是指向rc.local的符號鏈接。就是一般來說,自定義的程序不需要執行上面所說的繁瑣的建立shell增加鏈接文件的步驟,只需要將命令放在rc.local裏面就可以了,這個shell腳本就是保留給用戶自定義啓動內容的。


完成了系統所有的啓動任務後,linux會啓動終端或X-Window來等待用戶登錄。tty1,tty2,tty3...這表示在運行等級1,2,3,4的時候,都會執行"/sbin/mingetty",而且執行了6個,所以linux會有6個純文本終端,mingetty就是啓動終端的命令。

除了這6個之外還會執行"/etc/X11/prefdm-nodaemon"這個主要啓動X-Window,

至此,系統啓動完畢!


在系統啓動過程中主要的腳本和目錄有:

boot

/grub

/boot/grub/grub.conf

/boot/initrd+內核版本

/initrd文件中的/proc/  /sys/    /dev/ 目錄的掛載 及根的切換

/etc/inittab  腳本

/etc/rc.d/rc.sysinit  腳本 等


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