Linux啟動(dòng)過程剖析
Linux啟動(dòng)過程的剖析能幫助那些想深入學(xué)習(xí)Linux用戶建立一個(gè)相關(guān)Linux啟動(dòng)過程的清晰概念,進(jìn)而可以進(jìn)一步研究Linux接下來是如何工作的。
本文引用地址:http://butianyuan.cn/article/148603.htmLinux啟動(dòng)過程如下:當(dāng)用戶打開PC的電源,BIOS開機(jī)自檢,按BIOS中設(shè)置的啟動(dòng)設(shè)備(通常是硬盤)啟動(dòng),接著啟動(dòng)設(shè)備上安裝的引導(dǎo)程序lilo或grub開始引導(dǎo)Linux,Linux首先進(jìn)行內(nèi)核的引導(dǎo),接下來執(zhí)行init程序,init程序調(diào)用了rc.sysinit和rc等程序,rc.sysinit和rc當(dāng)完成系統(tǒng)初始化和運(yùn)行服務(wù)的任務(wù)后,返回init;init啟動(dòng)了mingetty后,打開了終端供用戶登錄系統(tǒng),用戶登錄成功后進(jìn)入了Shell,這樣就完成了從開機(jī)到登錄的整個(gè)啟動(dòng)過程。如圖所示:
下面分步來介紹下linux的啟動(dòng)過程:
1、BIOS自檢
當(dāng)你打開計(jì)算機(jī)電源,計(jì)算機(jī)會(huì)首先加載BIOS信息,BIOS信息是如此的重要,以至于計(jì)算機(jī)必須在最開始就找到它。這是因?yàn)锽IOS中包含了CPU的相關(guān)信息、設(shè)備啟動(dòng)順序信息、硬盤信息、內(nèi)存信息、時(shí)鐘信息、PnP特性等等。在此之后,計(jì)算機(jī)心里就有譜了,知道應(yīng)該去讀取哪個(gè)硬件設(shè)備了。
計(jì)算機(jī)在接通電源之后首先由BIOS進(jìn)行自檢,即進(jìn)行所謂的POST(Power ON Self Test),然后依據(jù)BIOS內(nèi)設(shè)置的引導(dǎo)順序從硬盤、軟盤或CDROM中讀入“引導(dǎo)塊”。 在 PC 中,引導(dǎo) Linux 是從 BIOS 中的地址 0xFFFF0 處開始的。BIOS 的第一個(gè)步驟是加電自檢(POST)。POST 的工作是對硬件進(jìn)行檢測。BIOS 的第二個(gè)步驟是進(jìn)行本地設(shè)備的枚舉和初始化。給定 BIOS 功能的不同用法之后,BIOS 由兩部分組成:POST 代碼和運(yùn)行時(shí)服務(wù)。當(dāng) POST 完成之后,它被從內(nèi)存中清理了出來,但是 BIOS 運(yùn)行時(shí)服務(wù)依然保留在內(nèi)存中,目標(biāo)操作系統(tǒng)可以使用這些服務(wù)。
要引導(dǎo)一個(gè)操作系統(tǒng),BIOS 運(yùn)行時(shí)會(huì)按照 CMOS 的設(shè)置定義的順序來搜索處于活動(dòng)狀態(tài)并且可以引導(dǎo)的設(shè)備。引導(dǎo)設(shè)備可以是軟盤、CD-ROM、硬盤上的某個(gè)分區(qū)、網(wǎng)絡(luò)上的某個(gè)設(shè)備,甚至是 USB 閃存。通常,Linux 都是從硬盤上引導(dǎo)的,其中主引導(dǎo)記錄(MBR)中包含主引導(dǎo)加載程序。
眾所周知,硬盤上第0磁道第一個(gè)扇區(qū)被稱為MBR,也就是Master Boot Record,即主引導(dǎo)記錄,它的大小是512字節(jié),別看地方不大,可里面卻存放了預(yù)啟動(dòng)信息、分區(qū)表信息。系統(tǒng)找到BIOS所指定的硬盤的MBR后,就會(huì)將其復(fù)制到0×7c00地址所在的物理內(nèi)存中。當(dāng) MBR 被加載到 RAM 中之后,BIOS 就會(huì)將控制權(quán)交給 MBR。其實(shí)被復(fù)制到物理內(nèi)存的內(nèi)容就是Boot Loader,而具體到你的電腦,那就是lilo或者grub了。
提取MBR的信息
要看MBR的內(nèi)容,請使用下面的命令
#從/dev/sda上讀取前512個(gè)字節(jié)的內(nèi)容,并將其寫入mbr.bin文件中
root@farsight:/home/linux# dd if=/dev/sda f=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
#以十六進(jìn)制和ASCII碼格式打印這個(gè)二進(jìn)制文件的內(nèi)容
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
……
這個(gè) dd 命令需要以 root 用戶的身份運(yùn)行,它從 /dev/hda(第一個(gè) IDE 盤) 上讀取前 512 個(gè)字節(jié)的內(nèi)容,并將其寫入 mbr.bin 文件中。od 命令會(huì)以十六進(jìn)制和 ASCII 碼格式打印這個(gè)二進(jìn)制文件的內(nèi)容。
2、啟動(dòng)GRUB/LILO
Boot Loader 就是在操作系統(tǒng)內(nèi)核運(yùn)行之前運(yùn)行的一段小程序。通過這段小程序,我們可以初始化硬件設(shè)備、建立內(nèi)存空間的映射圖,從而將系統(tǒng)的軟硬件環(huán)境帶到一個(gè)合適的狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核做好一切準(zhǔn)備。
Boot Loader有若干種,其中Grub、Lilo和spfdisk是常見的Loader。
GRUB和LILO都是引導(dǎo)加載程序,它們會(huì)引導(dǎo)操作系統(tǒng)。當(dāng)機(jī)器引導(dǎo)它的操作系統(tǒng)時(shí),BIOS會(huì)讀取引導(dǎo)介質(zhì)上最前面的512字節(jié)(即MBR: master boot record)。在單一的 MBR 中只能存儲(chǔ)一個(gè)操作系統(tǒng)的引導(dǎo)記錄,所以當(dāng)需要多個(gè)操作系統(tǒng)時(shí)就會(huì)出現(xiàn)問題。所以需要更靈活的引導(dǎo)加載程序。
GRUB 與 LILO 的比較
所有引導(dǎo)加載程序都以類似的方式工作,滿足共同的目的。不過,LILO 和 GRUB 之間有很多不同之處:
● LILO 沒有交互式命令界面,而 GRUB 擁有。
● LILO 不支持網(wǎng)絡(luò)引導(dǎo),而 GRUB 支持。
● LILO 將關(guān)于可以引導(dǎo)的操作系統(tǒng)位置的信息物理上存儲(chǔ)在 MBR 中。如果修改了 LILO 配置文件,必須將 LILO 第一階段引導(dǎo)加載程序重寫到 MBR。相對于 GRUB,這是一個(gè)更為危險(xiǎn)的選擇,因?yàn)殄e(cuò)誤配置的 MBR 可能會(huì)讓系統(tǒng)無法引導(dǎo)。使用 GRUB,如果配置文件配置錯(cuò)誤,則只是默認(rèn)轉(zhuǎn)到 GRUB 命令行界面。
安全提示:
關(guān)于安全性,任何可以接觸到引導(dǎo)磁盤/CD 的人,只需要使用沒有設(shè)置安全性的 grub.conf 或 lilo.conf,就可以繞過本文中提及的所有安全措施。特別是使用 GRUB 時(shí),因?yàn)槟軌蛞龑?dǎo)到單用戶模式,所以是一個(gè)嚴(yán)重的安全漏洞。解決此問題的一個(gè)簡單方法是在機(jī)器的 BIOS 中禁止通過 CD 和軟盤進(jìn)行引導(dǎo),并確保為 BIOS 設(shè)置了一個(gè)口令,使得其他人不能修改這些設(shè)置。
我們以Grub為例來講解。系統(tǒng)讀取內(nèi)存中的grub配置信息(一般為menu.lst或grub.lst),并依照此配置信息來啟動(dòng)不同的操作系統(tǒng)。
3、加載內(nèi)核
當(dāng)內(nèi)核映像被加載到內(nèi)存后,內(nèi)核階段就開始了。 內(nèi)核映像并不是一個(gè)可執(zhí)行的內(nèi)核,而是一個(gè)壓縮過的內(nèi)核映像。通常它是一個(gè)zImage(壓縮映像,小于512KB)或bzImage(較大的壓縮映像,大于512KB),它是提前使用zlib進(jìn)行壓縮的。在這個(gè)內(nèi)核映像前面是一個(gè)例程,它實(shí)現(xiàn)少量硬件設(shè)置,并對內(nèi)核映像中包含的內(nèi)核進(jìn)行解壓,然后將其放入高端內(nèi)存中,如果有初始RAM磁盤映像,就會(huì)將它移動(dòng)到內(nèi)存中,并標(biāo)明以后使用。然后此例程會(huì)調(diào)用內(nèi)核,并開始啟動(dòng)內(nèi)核引導(dǎo)的過程。
在GRUB命令中,我們可以使用initrd映像引導(dǎo)一個(gè)特定的內(nèi)核,方法如下:
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.
根據(jù)grub設(shè)定的內(nèi)核映像所在路徑,系統(tǒng)讀取內(nèi)存映像,并進(jìn)行解壓縮操作。此時(shí),屏幕一般會(huì)輸出“Uncompressing Linux”的提示。當(dāng)解壓縮內(nèi)核完成后,屏幕輸出“OK, booting the kernel”。 如果不知道要引導(dǎo)的內(nèi)核的名稱,只需使用/然后按下Tab鍵,就會(huì)顯示內(nèi)核和initrd映像列表。
系統(tǒng)將解壓后的內(nèi)核放置在內(nèi)存之中,并調(diào)用start_kernel()函數(shù)來啟動(dòng)一系列的初始化函數(shù)并初始化各種設(shè)備,完成Linux核心環(huán)境的建立。至此,Linux內(nèi)核已經(jīng)建立起來了,基于Linux的程序應(yīng)該可以正常運(yùn)行了。
4、執(zhí)行init進(jìn)程
init進(jìn)程是所有進(jìn)程的起點(diǎn),內(nèi)核在完成內(nèi)核引導(dǎo)后,即在本線程(進(jìn)程)空間內(nèi)加載init程序,它的進(jìn)程號為1。init進(jìn)程是所有進(jìn)程的發(fā)起者和控制者。因?yàn)樵谌魏位赨nix的系統(tǒng)(比如Linux)中,它都是第一個(gè)運(yùn)行的進(jìn)程,所以init進(jìn)程的編號(Process ID,PID)永遠(yuǎn)是1。如果init出現(xiàn)了問題,系統(tǒng)的其余部分也就隨之而垮掉了。
init進(jìn)程有兩個(gè)作用:
● 扮演終結(jié)父進(jìn)程的角色:所有的孤兒進(jìn)程都會(huì)被init進(jìn)程接管??焖賵?zhí)行一下ps -af 命令,可以列出許多父進(jìn)程ID(Parent Process ID,PPID)為1的進(jìn)程來。
● 進(jìn)入某個(gè)特定的運(yùn)行級別時(shí)運(yùn)行相應(yīng)的程序,以此對各種運(yùn)行級別進(jìn)行管理,這個(gè)作用由/etc/inittab文件定義的。 內(nèi)核被加載后,第一個(gè)運(yùn)行的程序便是/sbin/init,該文件會(huì)讀取/etc/inittab文件,并依據(jù)此文件來進(jìn)行初始化工作。
5、通過/etc/inittab文件進(jìn)行初始化
init進(jìn)程的工作是根據(jù)/etc/inittab來執(zhí)行相應(yīng)的腳本進(jìn)行系統(tǒng)初始化,如設(shè)置鍵盤、字體,裝載模塊,設(shè)置網(wǎng)絡(luò)等。其最主要的作用就是設(shè)定Linux的運(yùn)行等級,其設(shè)定形式是“:id:5:initdefault:”,這就表明Linux需要運(yùn)行在等級5上。Linux的運(yùn)行等級設(shè)定如下:
0:關(guān)機(jī)
1:單用戶模式
2:無網(wǎng)絡(luò)支持的多用戶模式
3:有網(wǎng)絡(luò)支持的多用戶模式
4:保留,未使用
5:有網(wǎng)絡(luò)支持有X-Window支持的多用戶模式
6:重新引導(dǎo)系統(tǒng),即重啟
對于RedHat來說,按以下順序執(zhí)行:
a、執(zhí)行/etc/rc.d/rc.sysinit(由init執(zhí)行的第一個(gè)腳本)
在設(shè)定了運(yùn)行等級后,Linux系統(tǒng)執(zhí)行的第一個(gè)用戶層文件就是/etc/rc.d/rc.sysinit腳本程序,它做的工作非常多,包括設(shè)定PATH、設(shè)定網(wǎng)絡(luò)配置(/etc/sysconfig/network)、啟動(dòng)swap分區(qū)、設(shè)定/proc、把root文件系統(tǒng)輸入到mtab、使用系統(tǒng)為裝入模塊做準(zhǔn)備、查找模塊的相關(guān)文件、檢查文件系統(tǒng),以進(jìn)行必要的修復(fù)、加載所有其他文件系統(tǒng)、清除幾個(gè)/etc文件,如/etc/mtab、/etc/fastboot和/etc/nologin、刪除UUCP的lock文件、刪除過時(shí)的子系統(tǒng)文件、刪除過時(shí)的pid文件、設(shè)置系統(tǒng)時(shí)鐘、打開交換、初始化串行端口、裝入模塊等等。如果你有興趣,可以到/etc/rc.d中查看一下rc.sysinit文件,里面的腳本夠你看幾天的。
b、執(zhí)行/etc/rc.d/rcX.d[KS]
首先終止K開頭的服務(wù)(用來關(guān)閉一個(gè)服務(wù)),然后啟動(dòng)S開頭的服務(wù)(用來啟動(dòng)一個(gè)服務(wù));對每一個(gè)運(yùn)行級別來說,在/etc/rc.d子目錄中都有一個(gè)對應(yīng)的下級目錄。這些運(yùn)行級別的下級子目錄的命名方法上rcX.d, 其中X就是代表運(yùn)行級別的數(shù)字。在各個(gè)運(yùn)行級別的子目錄中,都建立有到/etc/rc.d/init.d子目錄中命令腳本程序的符號鏈接。鏈接的名稱在K與S后有一個(gè)數(shù)字,表示執(zhí)行順序,數(shù)字小的先執(zhí)行如K01tog-pegasus 、 S00microcode_ctl。對以K開頭的腳本執(zhí)行時(shí)系統(tǒng)會(huì)傳遞stop參數(shù),而S開頭的腳本系統(tǒng)會(huì)傳遞start參數(shù)。
c、執(zhí)行/etc/rc.d/rc.local
Redhat中運(yùn)行模式2,3,5都把/etc/rc.d/rc.local作為初始化腳本中的最后一個(gè)文件,所以用戶可以自己在這個(gè)文件中添加一些需要在其他初始化工作之后,登陸之前執(zhí)行的命令。
你如果打開了此文件,里面有一句話,讀過之后,你就會(huì)對此命令的作用一目了然:
# 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留給用戶進(jìn)行個(gè)性化的地方。你可以把你想設(shè)置和啟動(dòng)的東西放到這里。
6、執(zhí)行/bin/login
login程序會(huì)提示使用者需輸入帳號與密碼,接著編碼并確認(rèn)密碼的正確性,若二者相合,則為使用者進(jìn)行初始化環(huán)境,并將控制權(quán)交給shell,即用戶登錄。
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)pid控制相關(guān)文章:pid控制原理
linux相關(guān)文章:linux教程
評論