Linux啟動過程的剖析能協助那些想深入學習Linux使用者建立一個相關Linux啟動過程的清晰概念,進而可以進一步研究Linux接下來是如何工作的。
Linux啟動過程如下:當使用者開啟PC的電源,BIOS開機自我測試 (POST),按BIOS中設定的啟動裝置(通常是硬碟)啟動,接著啟動裝置上安裝的引導程式lilo或grub開始引導Linux,Linux首先進行核心的引導,接下來執行init程式,init程式調用了rc.sysinit和rc等程式,rc.sysinit和rc當完成系統初始化和運行服務的任務後,返回init;init啟動了mingetty後,開啟了終端供使用者登入系統,使用者登入成功後進入了Shell,這樣就完成了從開機到登入的整個啟動過程。
下面分步來介紹下linux的啟動過程:
1) BIOS自檢
當你開啟電腦電源,電腦會首先載入BIOS資訊,BIOS資訊是如此的重要,以至於電腦必須在最開始就找到它。這是因為BIOS中包含了CPU的相關資訊、裝置啟動順序資訊、硬碟資訊、記憶體資訊、時鐘資訊、PnP特性等等。在此之後,電腦心裡就有譜了,知道應該去讀取哪個硬體裝置了。
電腦在接通電源之後首先由BIOS進行自檢,即進行所謂的POST(Power On Self Test),然後依據BIOS內設定的引導順序從硬碟、磁碟片或CDROM中讀入“引導塊”。 在 PC 中,引導 Linux 是從 BIOS 中的地址 0xFFFF0 處開始的。BIOS 的第一個步驟是加電自檢(POST)。POST 的工作是對硬體進行檢測。BIOS 的第二個步驟是進行本地裝置的枚舉和初始化。給定 BIOS 功能的不同用法之後,BIOS 由兩部分組成:POST 代碼和運行時服務。當 POST 完成之後,它被從記憶體中清理了出來,但是 BIOS 運行時服務依然保留在記憶體中,目標作業系統可以使用這些服務。
要引導一個作業系統,BIOS 運行時會按照 CMOS 的設定定義的順序來搜尋處於活動狀態並且可以引導的裝置。引導裝置可以是磁碟片、CD-ROM、硬碟上的某個分區、網路上的某個裝置,甚至是 USB 快閃記憶體。通常,Linux 都是從硬碟上引導的,其中主引導記錄(MBR)中包含主引導載入程式。
眾所周知,硬碟上第0磁軌第一個扇區被稱為MBR,也就是Master Boot Record,即主引導記錄,它的大小是512位元組,別看地方不大,可裡面卻存放了開機前資訊、分區表資訊。系統找到BIOS所指定的硬碟的MBR後,就會將其複製到0×7c00地址所在的實體記憶體中。當 MBR 被載入到 RAM 中之後,BIOS 就會將控制權交給 MBR。其實被複製到實體記憶體的內容就是Boot Loader,而具體到你的電腦,那就是lilo或者grub了。
提取MBR的資訊
要看MBR的內容,請使用下面的命令
#從/dev/sda上讀取前512個位元組的內容,並將其寫入mbr.bin檔案中
linux">root@farsight:/home/linux# dd if=/dev/sda of=mbr.bin bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000798615 seconds, 641 kB/s
#以十六進位和ASCII碼格式列印這個二進位檔案的內容
root@farsight:/home/linux# od -xa mbr.bin
0000000 48eb 1090 d08e 00bc b8b0 0000 d88e c08e
k H dle dle so P < nul 0 8 nul nul so X so @
0000020 befb 7c00 00bf b906 0200 a4f3 21ea 0006
{ > nul | ? nul ack 9 nul stx s $ j ! ack nul
0000040 be00 07be 0438 0b75 c683 8110 fefe 7507
nul > > bel 8 eot u vt etx F dle soh ~ ~ bel u
……
這個 dd 命令需要以 root 使用者的身份運行,它從 /dev/hda(第一個 IDE 盤) 上讀取前 512 個位元組的內容,並將其寫入 mbr.bin 檔案中。od 命令會以十六進位和 ASCII 碼格式列印這個二進位檔案的內容。
2)啟動GRUB/LILO
Boot Loader 就是在作業系統核心運行之前啟動並執行一段小程式。通過這段小程式,我們可以初始化硬體裝置、建立記憶體空間的映射圖,從而將系統的軟硬體環境帶到一個合適的狀態,以便為最終叫用作業系統核心做好一切準備。
Boot Loader有若干種,其中Grub、Lilo和spfdisk是常見的Loader。
GRUB和LILO都是引導載入程式,它們會引導作業系統。當機器引導它的作業系統時,BIOS會讀取引導介質上最前面的512位元組(即MBR: master boot record)。在單一的 MBR 中只能儲存一個作業系統的引導記錄,所以當需要多個作業系統時就會出現問題。所以需要更靈活的引導載入程式。
GRUB 與 LILO 的比較
所有引導載入程式都以類似的方式工作,滿足共同的目的。不過,LILO 和 GRUB 之間有很多不同之處:
l LILO 沒有互動式命令介面,而 GRUB 擁有。
l LILO 不支援網路引導,而 GRUB 支援。
l LILO 將關於可以引導的作業系統位置的資訊物理上儲存在 MBR 中。如果修改了 LILO 設定檔,必須將 LILO 第一階段引導載入程式重寫到 MBR。相對於 GRUB,這是一個更為危險的選擇,因為錯誤配置的 MBR 可能會讓系統無法引導。使用 GRUB,如果設定檔配置錯誤,則只是預設轉到 GRUB 命令列介面。
安全提示:
關於安全性,任何可以接觸到引導磁碟/CD 的人,只需要使用沒有設定安全性的 grub.conf 或 lilo.conf,就可以繞過本文中提及的所有安全措施。特別是使用 GRUB 時,因為能夠引導到單一使用者模式,所以是一個嚴重的安全性漏洞。解決此問題的一個簡單方法是在機器的 BIOS 中禁止通過 CD 和磁碟片進行引導,並確保為 BIOS 設定了一個口令,使得其他人不能修改這些設定。
我們以Grub為例來講解。系統讀取記憶體中的grub配置資訊(一般為menu.lst或grub.lst),並依照此配置資訊來啟動不同的作業系統。
3)載入核心
當核心映像被載入到記憶體後,核心階段就開始了。 核心映像並不是一個可執行檔核心,而是一個壓縮過的核心映像。通常它是一個zImage(壓縮映像,小於512KB)或bzImage(較大的壓縮映像,大於512KB),它是提前使用zlib進行壓縮的。在這個核心映像前面是一個常式,它實現少量硬體設定,並對核心映像中包含的核心進行解壓,然後將其放入高端記憶體中,如果有初始RAM磁碟映像,就會將它移動到記憶體中,並標明以後使用。然後此常式會調用核心,並開始啟動核心引導的過程。
在GRUB命令中,我們可以使用initrd映像引導一個特定的核心,方法如下:
grub> kernel /bzImage-2.6.14.2
[Linux-bzImage, setup=0x1400, size=0x29672e]
grub>initrd /initrd-2.6.14.2.img
[Linux-initrd @ 0x5f13000, 0xcc199 bytes]
grub> boot
Uncompressing Linux… Ok, booting the kernel.
根據grub設定的核心映像所在路徑,系統讀取記憶體映像,並進行解壓縮操作。此時,螢幕一般會輸出“Uncompressing Linux”的提示。當解壓縮核心完成後,螢幕輸出“OK, booting the kernel”。如果不知道要引導的核心的名稱,只需使用/然後按下Tab鍵,就會顯示核心和initrd映像列表。
系統將解壓後的核心放置在記憶體之中,並調用start_kernel()函數來啟動一系列的初始化函數並初始化各種裝置,完成Linux核心環境的建立。至此,Linux核心已經建立起來了,基於Linux的程式應該可以正常運行了。
3)執行init進程
init進程是所有進程的起點,核心在完成核心引導後,即在本線程(進程)空間內載入init程式,它的進程號為1。init進程是所有進程的發起者和控制者。因為在任何基於Unix的系統(比如Linux)中,它都是第一個啟動並執行進程,所以init進程的編號(Process ID,PID)永遠是1。如果init出現了問題,系統的其餘部分也就隨之而垮掉了。
init進程有兩個作用:
l 扮演終結父進程的角色:所有的孤兒進程都會被init進程接管。快速執行一下ps -af 命令,可以列出許多父進程ID(Parent Process ID,PPID)為1的進程來。
l 進入某個特定的運行層級時運行相應的程式,以此對各種運行層級進行管理,這個作用由/etc/inittab檔案定義的。 核心被載入後,第一個啟動並執行程式便是/sbin/init,該檔案會讀取/etc/inittab檔案,並依據此檔案來進行初始化工作。
5)通過/etc/inittab檔案進行初始化
init進程的工作是根據/etc/inittab來執行相應的指令碼進行系統初始化,如設定鍵盤、字型,裝載模組,設定網路等。其最主要的作用就是設定Linux的運行等級,其設定形式是“:id:5:initdefault:”,這就表明Linux需要運行在等級5上。Linux的運行等級設定如下:
0:關機
1:單一使用者模式
2:無網路支援的多使用者模式
3:有網路支援的多使用者模式
4:保留,未使用
5:有網路支援有X-Window支援的多使用者模式
6:重新引導系統,即重啟
對於RedHat來說,按以下順序執行:
a)執行/etc/rc.d/rc.sysinit(由init執行的第一個指令碼)
在設定了運行等級後,Linux系統執行的第一個使用者層檔案就是/etc/rc.d/rc.sysinit指令碼程式,它做的工作非常多,包括設定PATH、設定網路設定(/etc/sysconfig/network)、啟動swap分區、設定/proc、把root檔案系統輸入到mtab、使用系統為裝入模組做準備、尋找模組的相關檔案、檢查檔案系統,以進行必要的修複、載入所有其他檔案系統、清除幾個/etc檔案,如/etc/mtab、/etc/fastboot和/etc/nologin、刪除UUCP的lock檔案、刪除過時的子系統檔案、刪除過時的pid檔案、設定系統時鐘、開啟交換、初始化序列埠、裝入模組等等。如果你有興趣,可以到/etc/rc.d中查看一下rc.sysinit檔案,裡面的指令碼夠你看幾天的。
b)執行/etc/rc.d/rcX.d[KS]
首先終止K開頭的服務(用來關閉一個服務),然後啟動S開頭的服務(用來啟動一個服務);對每一個運行層級來說,在/etc/rc.d子目錄中都有一個對應的下級目錄。這些運行層級的下級子目錄的命名方法上rcX.d, 其中X就是代表運行層級的數字。在各個運行層級的子目錄中,都建立有到/etc/rc.d/init.d子目錄中命令指令碼程式的符號連結。連結的名稱在K與S後有一個數字,表示執行順序,數字小的先執行如K01tog-pegasus 、 S00microcode_ctl。對以K開頭的指令碼執行時系統會傳遞stop參數,而S開頭的指令碼系統會傳遞start參數。
c)執行/etc/rc.d/rc.local
Redhat中運行模式2,3,5都把/etc/rc.d/rc.local作為初始化指令碼中的最後一個檔案,所以使用者可以自己在這個檔案中添加一些需要在其他初始化工作之後,登陸之前執行的命令。
你如果開啟了此檔案,裡面有一句話,讀過之後,你就會對此命令的作用一目瞭然:
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don’t want to do the full Sys V style init stuff.
rc.local就是在一切初始化工作後,Linux留給使用者進行個人化的地方。你可以把你想設定和啟動的東西放到這裡。
6)執行/bin/login
login程式會提示使用者需輸入帳號與密碼,接著編碼並確認密碼的正確性,若二者相合,則為使用者進行初始化環境,並將控制權交給shell,即使用者登入。
原文出自【位元網】,轉載請保留原文連結:http://soft.chinabyte.com/os/232/12129232.shtml