Linux操做系統啓動流程詳解

1加電到BIOShtml

系統加電,BIOS(基本輸入輸出設備)CMOS(ROM)芯片內代碼裝載入內存linux

步驟1:上電自檢POST(Power-on self test),主要負責檢測系統外圍關鍵設備(如:CPU、內存、顯卡、I/O、鍵盤鼠標等)是否正常shell

步驟2:步驟1成功後,便會執行一段小程序用來枚舉本地設備並對其初始化。至此,BIOS的任務就完成了,此後將系統啓動的控制權移交到MBR部分的代碼。小程序

        PS: 在我的電腦中,Linux的啓動是從0xFFFF0地址開始的網絡

BIOS中包含了CPU的相關信息、設備啓動順序信息、硬盤信息、內存信息、時鐘信息、PnP特性等等ide


2讀取主引導設備MBR測試

系統找到BIOS所指定的主引導設備的MBR後,就會將其複製到0×7c00地址所在的物理內存中。其實被複制到物理內存的內容就是Boot Loader,而具體到你的電腦,那就是lilo或者grub/spfdisk字體

硬盤的0柱面、0磁頭、1扇區稱爲主引導扇區。它由三個部分組成,主引導程序(Bootloader 446byte)、 硬盤分區表DPT(Disk Partition table 64byte)和分區有效結束標誌(55,AA 2byte)magic numberui

磁盤分區表包含如下三部分:spa

       1)Partition ID  (5:延伸  82:Swap   83:Linux   8e:LVM     fd:RAID)

       2)Partition起始磁柱

       3)Partition的磁柱數量


3啓動bootloader      

Boot Loader 就是在操做系統內核運行以前運行的一段小程序。經過這段小程序,咱們能夠初始化硬件設備、創建內存空間的映射圖,從而將系統的軟硬件環境帶到一個合適的狀態,以便爲最終調用操做系統內核作好一切準備。

Boot Loader有若干種,其中Grub、Lilo和spfdisk是常見的Loader。


      一般狀況下,諸如lilo、grub這些常見的引導程序都直接安裝在MBR中。咱們以grub爲例來分析這個引導過程。

      grub引導也分爲兩個階段stage1階段和stage2階段(有些較新的grub又定義了stage1.5階段)。

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

[carl@localhost grub]$ hexdump stage1

0000000 48eb 0090 0000 0000 0000 0000 0000 0000

0000010 0000 0000 0000 0000 0000 0000 0000 0000

*

0000030 0000 0000 0000 0000 0000 0000 0000 0203

0000040 00ff 8000 0001 0000 0800 ebfa f607 80c2

0000050 0275 80b2 59ea 007c 3100 8ec0 8ed8 bcd0

0000060 2000 a0fb 7c40 ff3c 0274 c288 f652 80c2

0000070 5474 41b4 aabb cd55 5a13 7252 8149 55fb

0000080 75aa a043 7c41 c084 0575 e183 7401 6637

0000090 4c8b be10 7c05 44c6 01ff 8b66 441e c77c

00000a0 1004 c700 0244 0001 8966 085c 44c7 0006

00000b0 6670 c031 4489 6604 4489 b40c cd42 7213

00000c0 bb05 7000 7deb 08b4 13cd 0a73 c2f6 0f80

00000d0 f084 e900 008d 05be c67c ff44 6600 c031

00000e0 f088 6640 4489 3104 88d2 c1ca 02e2 e888

00000f0 f488 8940 0844 c031 d088 e8c0 6602 0489

0000100 a166 7c44 3166 66d2 34f7 5488 660a d231

0000110 f766 0474 5488 890b 0c44 443b 7d08 8a3c

0000120 0d54 e2c0 8a06 0a4c c1fe d108 6c8a 5a0c

0000130 748a bb0b 7000 c38e db31 01b8 cd02 7213

0000140 8c2a 8ec3 4806 607c b91e 0100 db8e f631

0000150 ff31 f3fc 1fa5 ff61 4226 be7c 7d7f 40e8

0000160 eb00 be0e 7d84 38e8 eb00 be06 7d8e 30e8

0000170 be00 7d93 2ae8 eb00 47fe 5552 2042 4700

0000180 6f65 006d 6148 6472 4420 7369 006b 6552

0000190 6461 2000 7245 6f72 0072 01bb b400 cd0e

00001a0 ac10 003c f475 00c3 0000 0000 0000 0000

00001b0 0000 0000 0000 0000 0000 0000 0000 1224

00001c0 090f be00 7dbd c031 13cd 8a46 800c 00f9

00001d0 0f75 dabe e87d ffc9 97eb 6c46 706f 7970

00001e0 bb00 7000 01b8 b502 b600 cd00 7213 b6d7

00001f0 b501 e94f fee0 0000 0000 0000 0000 aa55

0000200


      【外傳】定位硬盤的0頭0道2扇區的過程:

        BIOS將stage1載入內存0x7c00處並執行,而後調用BIOS INIT13中斷,將硬盤0頭0道2扇區內容載入內存0x7000處,而後調用copy_buffer將其轉移到內存0x8000處.在定位0頭0道2扇區時一般有兩種尋址方式:LBA和CHS


         2)、stage2:嚴格來講這裏還應該再區分個stage1.5的

         start.S加載stage1.5:stage1.5它存放在硬盤0頭0道3扇區向後的位置,stage1_5做爲stage1和stage2中間的橋樑,stage1_5有識別文件系統的能力,此後grub纔有能力去訪問/boot分區/boot/grub目錄下的 stage2文件,將stage2載入內存並執行


         start.S加載stage2:一樣,這個stage2也不是/boot分區/boot/grub目錄下的stage2,這個時候start.S讀取的是存放在/boot分區Boot Sector的stage2。這種狀況下就有一個限制:由於start.S經過BIOS中斷方式直接對硬盤尋址(而非經過訪問具體的文件系統),其尋址範圍有限,限制在8GB之內。所以這種狀況須要將/boot分區分在硬盤8GB尋址空間以前。

         假如是情形2,咱們將/boot/grub目錄下的內容清空,依然能成功啓動grub;假如是情形1,將/boot/grub目錄下stage2刪除後,則系統啓動過程當中grub會啓動失敗。

    

    4加載內核

    當stage2被載入內存執行時,它首先會去解析grub的配置文件/boot/grub/grub.conf,而後加載內核鏡像到內存中,並將控制權轉交給內核。而內核會當即初始化系統中各設備並作相關的配置工做,其中包括CPU、I/O、存儲設備等。

    Linux的內核鏡像僅是包含了基本的硬件驅動,在系統安裝過程當中會檢測系統硬件信息,根據安裝信息和系統硬件信息將一部分設備驅動寫入 initrd 。這樣在之後啓動系統時,一部分設備驅動就放在initrd中來加載。

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

    一部分設備驅動就放在initrd中來加載,bootloader initialized RAM disk,就是由 boot loader 初始化的內存盤。


    initramfs 是在 kernel 2.5中引入的技術,實際上它的含義就是:在內核鏡像中附加一個cpio包,這個cpio包中包含了一個小型的文件系統,當內核啓動時,內核將這個 cpio包解開,而且將其中包含的文件系統釋放到rootfs中,內核中的一部分初始化代碼會放到這個文件系統中,做爲用戶層進程來執行。這樣帶來的明顯的好處是精簡了內核的初始化代碼,並且使得內核的初始化過程更容易定製。親自驗證4.7內核採用initramfs,2.6內核兩種都有,具體哪種是默認啓用的沒驗證過。


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


   5初始化系統

   通過千辛萬苦的跋涉,咱們終於接近黎明的曙光了。接下來就是最後一步了:初始化系統。/sbin/init進程是系統其餘全部進程的父進程,當它接管了系統的控制權先以後,它首先會去讀取/etc/inittab文件來執行相應的腳本進行系統初始化,如設置鍵盤、字體,裝載模塊,設置網絡等.

Linux的運行等級設定以下:

0:關機

1:單用戶模式

2:無網絡支持的多用戶模式

3:有網絡支持的多用戶模式

4:保留,未使用

5:有網絡支持有X-Window支持的多用戶模式

6:從新引導系統,即重啓

   

   主要包括如下工做:

   1)、執行系統初始化腳本(/etc/rc.d/rc.sysinit),對系統進行基本的配置,以讀寫方式掛載根文件系統及其它文件系統,到此係統算是基本運行起來了,後面須要進行運行級別的肯定及相應服務的啓動。rc.sysinit所作的事情(不一樣的Linux發行版,該文件可能有些差別)以下:

(1)獲取網絡環境與主機類型。首先會讀取網絡環境設置文件"/etc/sysconfig/network",獲取主機名稱與默認網關等網絡環境。

(2)測試與載入內存設備/proc及usb設備/sys。除了/proc外,系統會主動檢測是否有usb設備,並主動加載usb驅動,嘗試載入usb文件系統。

(3)決定是否啓動SELinux。

(4)接口設備的檢測與即插即用(pnp)參數的測試。

(5)用戶自定義模塊的加載。用戶能夠再"/etc/sysconfig/modules/*.modules"加入自定義的模塊,此時會加載到系統中。

(6)加載核心的相關設置。按"/etc/sysctl.conf"這個文件的設置值配置功能。

(7)設置系統時間(clock)。

(8)設置終端的控制檯的字形。

(9)設置raid及LVM等硬盤功能。

(10)以方式查看檢驗磁盤文件系統。

(11)進行磁盤配額quota的轉換。

(12)從新以讀取模式載入系統磁盤。

(13)啓動quota功能。

(14)啓動系統隨機數設備(產生隨機數功能)。

(15)清楚啓動過程當中的臨時文件。

(16)將啓動信息加載到"/var/log/dmesg"文件中。

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下的文件。

/etc/init.d-> /etc/rc.d/init.d

/etc/rc ->/etc/rc.d/rc

/etc/rc*.d ->/etc/rc.d/rc*.d

/etc/rc.local-> /etc/rc.d/rc.local

/etc/rc.sysinit-> /etc/rc.d/rc.sysinit

也就是說,/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腳本就是保留給用戶自定義啓動內容的。


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

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

6執行/bin/login程序,進入登陸狀態

拋出command line interface,等待用戶登陸

wKioL1fNS8iSgzhOAAJAGDzjwLg986.jpg-wh_50

至此,系統就啓動完畢了。以上分析不到的地方還請各位大蝦不吝指正。

參考博文:

        http://blog.csdn.net/miss_acha/article/details/50004717

        http://blog.chinaunix.net/uid-30565002-id-5540367.html

相關文章
相關標籤/搜索