既然啓動是很嚴肅的一件事,那咱們就來了解一下整個啓動的過程吧! 好讓你們比較容易發現啓動過程裏面可能會發生問題的地方,以及出現問題後的解決之道! 不過,由於啓動的過程當中,那個啓動管理程序 (Boot Loader) 使用的軟件可能不同,例如目前各大 Linux distributions 的主流爲 grub,但早期 Linux 默認是使用 LILO 。 但不管如何,咱們老是得要了解整個 boot loader 的工做狀況,才能瞭解爲什麼進行多重啓動的配置時, 總是聽人家講要先安裝 Windows 再安裝 Linux 的緣由~php
假設以我的計算機架設的 Linux 主機爲例 , 當你按下電源按鍵後計算機硬件會主動的讀取 BIOS 來加載硬件資訊及進行硬件系統的自我測試, 以後系統會主動的去讀取第一個可啓動的裝置 (由 BIOS 配置的) ,此時就能夠讀入啓動管理程序了。node
啓動管理程序能夠指定使用哪一個核心文件來啓動,並實際加載核心到內存當中解壓縮與運行, 此時核心就可以開始在內存內活動,並偵測全部硬件資訊與加載適當的驅動程序來使整部主機開始運行, 等到核心偵測硬件與加載驅動程序完畢後,一個最陽春的操做系統就開始在你的 PC 上面跑了。linux
主機系統開始運行後,此時 Linux 纔會呼叫外部程序開始準備軟件運行的環境, 而且實際的加載全部系統運行所須要的軟件程序哩!最後系統就會開始等待你的登錄與操做啦! 簡單來講,系統啓動的通過能夠彙整成底下的流程的:shell
在我的計算機架構下,你想要啓動整部系統首先就得要讓系統去加載 BIOS (Basic Input Output System),並透過 BIOS 程序去加載 CMOS 的資訊,而且藉由 CMOS 內的配置值取得主機的各項硬件配置, 例如 CPU 與周邊設備的溝通時脈啊、啓動裝置的搜尋順序啊、硬盤的大小與類型啊、 系統時間啊、各周邊匯流排的是否啓動 Plug and Play (PnP, 隨插即用裝置) 啊、 各周邊設備的 I/O 位址啊、以及與 CPU 溝通的 IRQ 岔斷等等的資訊。windows
在取得這些資訊後,BIOS 還會進行啓動自我測試 (Power-on Self Test, POST) 。 而後開始運行硬件偵測的初始化,並配置 PnP 裝置,以後再定義出可啓動的裝置順序, 接下來就會開始進行啓動裝置的數據讀取了 (MBR 相關的任務開始)。bash
由於咱們的系統軟件大多放置到硬盤中嘛!因此 BIOS 會指定啓動的裝置好讓咱們能夠讀取磁碟中的操做系統核心文件。 但由於不一樣的操做系統他的文件系統格式不相同,所以咱們必需要以一個啓動管理程序來處理核心文件加載 (load) 的問題, 所以這個啓動管理程序就被稱爲 Boot Loader 了。那這個 Boot Loader 程序安裝在哪裏呢?就在啓動裝置的第一個磁區 (sector) 內,也就是咱們一直談到的 MBR (Master Boot Record, 主要啓動記錄區)。網絡
那你會不會以爲很奇怪啊?既然核心文件須要 loader 來讀取,那每一個操做系統的 loader 都不相同, 這樣的話 BIOS 又是如何讀取 MBR 內的 loader 呢?頗有趣的問題吧!其實 BIOS 是透過硬件的 INT 13 中斷功能來讀取 MBR 的,也就是說,只要 BIOS 可以偵測的到你的磁碟 (不論該磁碟是 SATA 仍是 IDE 介面),那他就有辦法透過 INT 13 這條通道來讀取該磁碟的第一個磁區內的 MBR 啦!這樣 boot loader 也就可以被運行羅!架構
咱們知道每顆硬盤的第一個磁區內含有 446 bytes的 MBR 區域,那麼若是個人主機上面有兩顆硬盤的話, 系統會去哪顆硬盤的 MBR 讀取 boot loader 呢?這個就得要看 BIOS 的配置了。 基本上,咱們經常講的『系統的 MBR』其實指的是 第一個啓動裝置的 MBR 纔對! 因此,改天若是你要將啓動管理程序安裝到某顆硬盤的 MBR 時, 要特別注意當時系統的『第一個啓動裝置』是哪一個,不然會安裝到錯誤的硬盤上面的 MBR 喔! 測試
剛剛說到 Loader 的最主要功能是要認識操做系統的文件格式並據以加載核心到主內存中去運行。 由於不一樣操做系統的文件格式不一致,所以每種操做系統都有本身的 boot loader 啦!用本身的 loader 纔有辦法加載核心文件嘛!那問題就來啦,你應該有據說過多重操做系統吧?也就是在一部主機上面安裝多種不一樣的操做系統。 既然你 (1)必需要使用本身的 loader 纔可以加載屬於本身的操做系統核心,而 (2)系統的 MBR 只有一個,那你怎麼會有辦法同時在一部主機上面安裝 Windows 與 Linux 呢?spa
其實每一個文件系統 (filesystem, 或者是 partition) 都會保留一塊啓動磁區 (boot sector) 提供操做系統安裝 boot loader , 而一般操做系統默認都會安裝一份 loader 到他根目錄所在的文件系統的 boot sector 上。若是咱們在一部主機上面安裝 Windows 與 Linux 後,該 boot sector, boot loader 與 MBR 的相關性會有點像下圖:
如上圖所示,每一個操做系統默認是會安裝一套 boot loader 到他本身的文件系統中 (就是每一個 filesystem 左下角的方框),而在 Linux 系統安裝時,你能夠選擇將 boot loader 安裝到 MBR 去,也能夠選擇不安裝。 若是選擇安裝到 MBR 的話,那理論上你在 MBR 與 boot sector 都會保有一份 boot loader 程序的。 至於 Windows 安裝時,他默認會主動的將 MBR 與 boot sector 都裝上一份 boot loader!因此啦, 你會發現安裝多重操做系統時,你的 MBR 經常會被不一樣的操做系統的 boot loader 所覆蓋啦! ^_^
咱們剛剛提到的兩個問題仍是沒有解決啊!雖然各個操做系統均可以安裝一份 boot loader 到他們的 boot sector 中, 這樣操做系統能夠透過本身的 boot loader 來加載核心了。問題是系統的 MBR 只有一個哩! 你要怎麼運行 boot sector 裏面的 loader 啊?
boot loader 主要的功能以下:
由於具備菜單功能,所以咱們能夠選擇不一樣的核心來啓動。而由於具備控制權轉交的功能,所以咱們能夠加載其餘 boot sector 內的 loader 啦!不過 Windows 的 loader 默認不具備控制權轉交的功能,所以你不能使用 Windows 的 loader 來加載 Linux 的 loader 喔!這也是爲啥第三章談到 MBR 與多重啓動時,會特別強調先裝 Windows 再裝 Linux 的緣故。 咱們將上述的三個功能以底下的圖示來解釋你就看的懂了!(與第三章的圖示也很是相似啦!)
如上圖所示,個人 MBR 使用 Linux 的 grub 這個啓動管理程序,而且裏面假設已經有了三個菜單, 第一個菜單能夠直接指向 Linux 的核心文件而且直接加載核心來啓動;第二個菜單能夠將啓動管理程序控制權交給 Windows 來管理,此時 Windows 的 loader 會接管啓動流程,這個時候他就可以啓動 windows 了。第三個菜單則是使用 Linux 在 boot sector 內的啓動管理程序,此時就會跳出另外一個 grub 的菜單啦!瞭解了嗎?
而最終 boot loader 的功能就是『加載 kernel 文件』啦!
當咱們藉由 boot loader 的管理而開始讀取核心文件後,接下來, Linux 就會將核心解壓縮到主內存當中, 而且利用核心的功能,開始測試與驅動各個周邊裝置,包括儲存裝置、CPU、網絡卡、聲卡等等。 此時 Linux 核心會以本身的功能從新偵測一次硬件,而不必定會使用 BIOS 偵測到的硬件資訊喔!也就是說,核心此時纔開始接管 BIOS 後的工做了。 那麼核心文件在哪裏啊?通常來講,他會被放置到 /boot 裏面,而且取名爲 /boot/vmlinuz 纔對!
[root@www ~]# ls --format=single-column -F /boot config-2.6.18-92.el5 <==此版本核心被編譯時選擇的功能與模塊配置檔 grub/ <==就是啓動管理程序 grub 相關數據目錄 initrd-2.6.18-92.el5.img <==虛擬文件系統檔! System.map-2.6.18-92.el5 <==核心功能放置到內存位址的對應表 vmlinuz-2.6.18-92.el5 <==就是核心文件啦!最重要者!
從上表咱們也能夠知道此版本的 Linux 核心爲 2.6.18-92.el5 這個版本!爲了硬件開發商與其餘核心功能開發者的便利, 所以 Linux 核心是能夠透過動態加載核心模塊的 (就請想成驅動程序便可),這些核心模塊就放置在 /lib/modules/ 目錄內。 因爲模塊放置到磁盤根目錄內 (要記得 /lib 不能夠與 / 分別放在不一樣的 partition !), 所以在啓動的過程當中核心必需要掛載根目錄,這樣纔可以讀取核心模塊提供加載驅動程序的功能。 並且爲了擔憂影響到磁碟內的文件系統,所以啓動過程當中根目錄是以惟讀的方式來掛載的喔。
通常來講,非必要的功能且能夠編譯成爲模塊的核心功能,目前的 Linux distributions 都會將他編譯成爲模塊。 所以 U盤, SATA, SCSI... 等磁碟裝置的驅動程序一般都是以模塊的方式來存在的。 如今來思考一種狀況,假設你的 linux 是安裝在 SATA 磁碟上面的,你能夠透過 BIOS 的 INT 13 取得 boot loader 與 kernel 文件來啓動,而後 kernel 會開始接管系統而且偵測硬件及嘗試掛載根目錄來取得額外的驅動程序。
問題是,核心根本不認識 SATA 磁碟,因此須要加載 SATA 磁碟的驅動程序, 不然根本就沒法掛載根目錄。可是 SATA 的驅動程序在 /lib/modules 內,你根本沒法掛載根目錄又怎麼讀取到 /lib/modules/ 內的驅動程序?是吧!很是的兩難吧!在這個狀況之下,你的 Linux 是沒法順利啓動的! 那怎辦?不要緊,咱們能夠透過虛擬文件系統來處理這個問題。
虛擬文件系統 (Initial RAM Disk) 通常使用的檔名爲 /boot/initrd ,這個文件的特點是,他也可以透過 boot loader 來加載到內存中, 而後這個文件會被解壓縮而且在內存當中模擬成一個根目錄, 且此模擬在內存當中的文件系統可以提供一支可運行的程序,透過該程序來加載啓動過程當中所最須要的核心模塊, 一般這些模塊就是 U盤, RAID, LVM, SCSI 等文件系統與磁碟介面的驅動程序啦!等加載完成後, 會幫助核心從新呼叫 /sbin/init 來開始後續的正常啓動流程。
如上圖所示,boot loader 能夠加載 kernel 與 initrd ,而後在內存中讓 initrd 解壓縮成爲根目錄, kernel 就可以藉此加載適當的驅動程序,最終釋放虛擬文件系統,並掛載實際的根目錄文件系統, 就可以開始後續的正常啓動流程。更詳細的 initrd 說明,你能夠自行使用 man initrd 去查閱看看。 底下讓咱們來了解一下 CentOS 5.x 的 initrd 文件內容有什麼吧!
# 1. 先將 /boot/initrd 複製到 /tmp/initrd 目錄中,等待解壓縮: [root@www ~]# mkdir /tmp/initrd [root@www ~]# cp /boot/initrd-2.6.18-92.el5.img /tmp/initrd/ [root@www ~]# cd /tmp/initrd [root@www initrd]# file initrd-2.6.18-92.el5.img initrd-2.6.18-92.el5.img: gzip compressed data, ... # 原來是 gzip 的壓縮檔!由於是 gzip ,因此擴展名給他改爲 .gz 吧! # 2. 將上述的文件解壓縮: [root@www initrd]# mv initrd-2.6.18-92.el5.img initrd-2.6.18-92.el5.gz [root@www initrd]# gzip -d initrd-2.6.18-92.el5.gz [root@www initrd]# file initrd-2.6.18-92.el5 initrd-2.6.18-92.el5: ASCII cpio archive (SVR4 with no CRC) # 搞了老半天,原來仍是 cpio 的命令壓縮成的文件啊!解壓縮看看! # 3. 用 cpio 解壓縮 [root@www initrd]# cpio -ivcdu < initrd-2.6.18-92.el5 [root@www initrd]# ll drwx------ 2 root root 4096 Apr 10 02:05 bin drwx------ 3 root root 4096 Apr 10 02:05 dev drwx------ 2 root root 4096 Apr 10 02:05 etc -rwx------ 1 root root 1888 Apr 10 02:05 init -rw------- 1 root root 5408768 Apr 10 02:00 initrd-2.6.18-92.el5 drwx------ 3 root root 4096 Apr 10 02:05 lib drwx------ 2 root root 4096 Apr 10 02:05 proc lrwxrwxrwx 1 root root 3 Apr 10 02:05 sbin -> bin drwx------ 2 root root 4096 Apr 10 02:05 sys drwx------ 2 root root 4096 Apr 10 02:05 sysroot # 看!是否很像根目錄!尤爲也是有 init 這個運行檔!務必看一下權限! # 接下來看看 init 這個文件內有啥咚咚? # 4. 觀察 init 文件內較重要的運行項目 [root@www initrd]# cat init #!/bin/nash <==使用相似 bash 的 shell 來運行 mount -t proc /proc /proc <==掛載內存的虛擬文件系統 ....(中間省略).... echo Creating initial device nodes mknod /dev/null c 1 3 <==建立系統所須要的各項裝置! ....(中間省略).... echo "Loading ehci-hcd.ko module" insmod /lib/ehci-hcd.ko <==加載各項核心模塊,就是驅動程序! ....(中間省略).... echo Creating root device. mkrootdev -t ext3 -o defaults,ro hdc2 <==嘗試掛載根目錄啦! ....(底下省略)....
透過上述運行檔的內容,咱們能夠知道 initrd 有加載模塊而且嘗試掛載了虛擬文件系統。 接下來就可以順利的運行啦!那麼是否必定須要 initrd 呢?
是否沒有 initrd 就沒法順利啓動? 答: 不見得的!須要 initrd 最重要的緣由是,當啓動時沒法掛載根目錄的狀況下, 此時就必定須要 initrd ,例如你的根目錄在特殊的磁碟介面 (U盤, SATA, SCSI) , 或者是你的文件系統較爲特殊 (LVM, RAID) 等等,纔會須要 initrd。 若是你的 Linux 是安裝在 IDE 介面的磁碟上,而且使用默認的 ext2/ext3 文件系統, 那麼不須要 initrd 也可以順利的啓動進入 Linux 的!
在覈心完整的加載後,您的主機應該就開始正確的運行了
轉自 http://vbird.dic.ksu.edu.tw/linux_basic/0510osloader_1.php