【Linux】計算機的啟動過程
計算機啟動是一個非常複雜的過程,大致可以分為四個步驟。
1.第一階段:BIOS
BIOS是固化到計算機主機板上一個ROM晶片上的一段程式,這段程式的主要作用有兩個。
1.硬體自檢Power-On Self-Test
按下電源鍵後,計算機首先會讀取BIOS,然後BIOS檢查計算機硬體有沒有問題,是否滿足執行條件,這個過程叫做“硬體自檢”。如果硬體有問題,電腦上的speaker會發出蜂鳴聲,根據不同的聲音,可以大致判斷那部分硬體出現了問題,比如,電腦按下電源鍵發出短促持續的滴滴聲,很有可能是記憶體條鬆了。如果沒有問題,則會在螢幕上顯示CPU、記憶體、硬碟等硬體資訊。
2.獲得啟動順序,轉交控制權
硬體自檢通過後,BIOS就要轉交控制權,那麼到底應該交給誰呢?在BIOS當中有一個外部裝置的排序,排在前面的裝置就是優先轉交控制權的裝置。這種排序叫做”啟動順序”(Boot Sequence)。
這就是為什麼用U盤裝系統的時候要將U盤設定為第一啟動項。
2.第二階段:MBR(主引導記錄)
BIOS根據啟動順序,將控制權轉交給排在第一位的啟動裝置。
此時,計算機將這個啟動裝置的第一個扇區,即boot sector讀入記憶體。這個扇區的大小是512位元組,這512個位元組可以分為三個部分(參見上一篇文章)。
內容 | 位元組 |
---|---|
MBR | 前446位元組 |
DPT | 64位元組 |
BRID | 2位元組 |
計算機判斷這512位元組的最後兩個位元組是否為0x55和0xAA。如果是,則表明這個裝置可以用於啟動,如果不是,則將控制權轉交給排在第二位的啟動裝置。重複這個過程,直到找到可以啟動的裝置。
主引導記錄只有446個位元組,裡面一般裝的是一個引導載入程式(boot loader)(嚴格來講,只是boot loader的主程式),在Linux系統中一般是grub。引導載入程式會在分割槽表中找到活動分割槽(如果某個分割槽記錄的第一個位元組值為0x80,則該分割槽為活動分割槽,0x00表示非活動分割槽),從活動分割槽當中載入核心到記憶體當中來。
在命令列輸入fdisk -l ,即可檢視那個分割槽是啟用分割槽
在/dev/sda1後面有一個*號,表示這個分割槽是活動分割槽。
3.第三階段:載入核心
boot loader開始讀取核心檔案後,接下來,Linux就會將核心解壓縮到記憶體當中,並且利用核心的功能開始測試與驅動各個周邊裝置,包括儲存裝置、CPU、網絡卡、音效卡等。此時,Linux核心會重新檢測一次硬體,不一定會用BIOS檢測到的硬體資訊。也就是說,核心此時才開始接管BIOS的工作。核心檔案一般放在/boot當中,名字為/boot/vmlinux.
4.第四階段:執行第一個程序init
在核心載入完畢進行完硬體檢測和驅動程式載入後,計算機的硬體應該已經準備就緒了。此時,核心會主動呼叫第一個程序,就是/sbin/init。init程序主要工作有下面幾個:
1.獲得執行級別
init程序首先讀取的檔案是/etc/inittab,獲得執行級別。這個檔案其實只有一句話,就是設定預設的執行級別。
(centos6和centos5有些區別,centos5的/etc/inittab檔案當中出了設定預設執行級別外,還有其他內容。Centos 6弱化了inittab檔案的作用)
inittab檔案的內容如下:
# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
#
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:3:initdefault:
前面全部都是註釋,只有最後一行設定了預設的執行級別。
2.呼叫/etc/rc.d/rc.sysinit進行系統初始化
init程序確定了執行級別之後,開始呼叫/etc/rc.d/rc.sysinit指令碼,進行系統初始化,這個指令碼的工作有很多,具體的工作請參看《鳥哥的Linux私房菜》。
3.根據執行級別啟動系統服務
系統初始化完成後,init程序根據inittab設定的執行級別(假設為N),執行/etc/rcN.d/*目錄下的所有指令碼(其實是連結檔案,真實指令碼在另外一個資料夾)。
這個目錄下的連結檔案均已K或S開頭,K表示要關閉的服務,S表示要啟動的服務。數字表示執行的順序。
4.執行使用者自定義開機啟動程式(/etc/rc.d/rc.local)
/etc/rc.d/rc.local這個檔案用於執行使用者自定義的開機啟動程式,如果你想啟動某個指令碼,或執行某項命令,直接將其寫入這個檔案,那麼這個指令碼或命令在計算機啟動時就會被執行。這個檔案預設只有一行。
就是將/var/lock/subsys/local這個檔案“摸”了一下,沒有改變這個檔案的內容,事實上,這個檔案是空的。摸一下這個檔案僅僅更新了這個檔案的修改時間,即修改時間戳,就是說rc.local的程式已經啟動了, 防止重複執行。
5.init執行終端模擬程式mingetty來啟動login程序,最後等待使用者登入。
至此,計算機總算是啟動了,這個過程真是無比的艱難。