在日常生活中,我們開機的操作一般為按下電源鍵,等待系統自己起來就好了。這開機的過程看似簡單,但其中卻包含着十分複雜的各種小過程。以Linux為例,其流程為下圖所示:

一、POST
首先,先介紹下BIOS和POST的概念。
BIOS:Basic Input Output System,即基本輸入輸出系統,它是一組固化到計算機内主機闆上一個ROM晶片上的程式,它儲存着計算機最重要的基本輸入輸出的程式、開機後自檢程式和系統自啟動程式,它可從CMOS中讀寫系統設定的具體資訊。其主要功能是為計算機提供最底層的、最直接的硬體設定和控制。
POST:Power on self test,即加電自檢,它是BIOS功能的一個部分,責完成對CPU、主機闆、記憶體、軟硬碟子系統、顯示子系統(包括顯示緩存)、串并行接口、鍵盤、CD-ROM光驅等的檢測。主要檢查硬體的好壞。
當我們按下電源鍵時,BIOS就會先啟動POST功能,檢查自身硬體的狀态并回報,如果硬體有問題則會導緻系統啟動失敗。如果硬體正常,則進入下一步。
二、BootSequence
bootsequence為啟動順序,可在BIOS中設定。如下圖:
BIOS會根據次序查找各引導裝置,其查找到的第一個有引導程式(bootloader)的裝置即為本次啟動要用到的裝置。
以硬碟啟動為例,BIOS此時去讀取硬碟驅動器的第一個扇區(MBR,512位元組),然後執行裡面的代碼。實際上這裡BIOS并不關心啟動裝置第一個扇區中是什麼内容,它隻是負責讀取該扇區内容、并執行。
至此,BIOS的任務就完成了,此後将系統啟動的控制權移交到MBR部分的代碼。
三、Bootloader(MBR)
MBR:Master Boot Record,即主引導記錄,是硬碟驅動器上的第一個扇區,它的大小為512Bytes,由三個部分組成。分别為主引導程式(Bootloader)、硬碟分區表DPT(Disk Partition table)和硬碟有效标志(55AA),其大小分别為446Bytes,64Bytes和2Bytes。
BootLoader是在作業系統核心運作之前運作的程式。它可以初始化硬體裝置、建立記憶體空間映射圖,進而将系統的軟硬體環境帶到一個合适狀态,以便為最終調用作業系統核心準備好正确的環境。
在Linux中,常用的bootloader有grub和lilo,我們以grub為例:
grub:Grand Uniform Bootloader,它是一個多重作業系統管理器,可以引導不同的作業系統。一般來說,它的引導有2個階段stage1和stage2:
stage1:stage1的代碼是存放在MBR中的前446Bytes中的,也就是說,BIOS會先把它加載到記憶體中執行。stage1沒有識别檔案系統的能力,它僅僅是是stage2的入口。
stage1_5:stage1_5是MBR之後的扇區,它可以讓stage1中的bootloader識别stage2所在的分區上的檔案系統,是stage1和stage2之間的橋梁。
stage2:現在可以通路/boot/grub/中的stage2檔案,并将其裝入記憶體中執行。它的作用為:
(1)提供菜單、并提供互動式接口
e:編輯模式,用于編輯菜單
c:指令模式,互動式接口
(2)加載使用者選擇的核心或作業系統
允許傳遞參數給核心
可隐藏此菜單
(3)為菜單提供了保護機制
為編輯菜單提供認證
為啟用核心或作業系統提供認證
四、Kernel
當stage2被裝入記憶體中執行後,它會去解析/boot/grub/grub.conf檔案,并根據該配置檔案來加載Kernel(核心)鏡像和initrd至記憶體。此時,核心将得到系統控制權并立即初始化系統中各裝置并做相關的配置工作,其中包括CPU、I/O、儲存設備等。
initrd:bootloader initialized RAM disk,即為bootloader初始化的記憶體盤。因為核心在初始化系統各硬體裝置時需要加載不同的驅動程式,而每個系統的硬體架構并不是相同的,核心編譯了一部分硬體驅動,而另一部分則被放置在initrd中。
實際上Linux的核心鏡像僅是包含了基本的硬體驅動,在系統安裝過程中會檢測系統硬體資訊,根據安裝資訊和系統硬體資訊将一部分裝置驅動寫入initrd。這樣在以後啟動系統時,一部分裝置驅動就放在initrd中來加載。
注:initramfs是initrd的更新優化。
核心在獲得控制權初始化後,會去執行initrd中的init腳本,這時核心将控制權交給了init檔案處理。當所需的驅動程式加載完後,會建立一個根裝置,然後将根檔案系統rootfs以隻讀的方式挂載。這一步結束後,釋放未使用的記憶體,并通過switchroot轉換到真正的根檔案系統上面去,同時運作/sbin/init程式。此後系統的控制權就全權交給/sbin/init程序了。
五、/sbin/init
1、運作級别:
/sbin/init程序是用來初始化系統的程序,它是所有程序的父程序。當/sbin/init程序獲得了系統的控制權之後,它會先讀取/etc/inittab檔案來确定系統的運作級别。
CentOS6.7的/etc/inittab檔案:
[root@localhost initrd]# vim /etc/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:
~
~
運作級别是為了系統的運作或維護等目的而設定的機制,一共有7個級别,分别用數字0-6表示:
0:關機,shutdown
1:單使用者模式(single user),root使用者,無需認證;維護模式
2:多使用者模式(multi user),會啟動網絡功能,但不會啟動NFS;維護模式
3:多使用者模式(multi user),完全功能模式;文本界面,無圖形界面
4:預留級别:目前無特别使用目的,但習慣以同3級别功能使用
5:多使用者模式(multi user),完全功能模式,圖形界面
6:重新開機,reboot
預設級别一般為3或5。
2、系統初始化
确定運作級别後,/sbin/init程式會讀取/etc/rc.d/rc.sysinit這個系統初始化腳本進行系統初始化操作,包括以下部分:
a、讀取/etc/sysconfig/network/檔案來設定主機名
b、設定歡迎資訊
c、激活udev和selinux
d、挂載/etc/fstab檔案中定義的所有檔案系統
e、檢測根檔案系統,并以讀寫方式重新挂載根檔案系統
f、設定系統時鐘
g、根據/etc/sysctl.conf檔案來設定核心參數
h、激活lvm及軟raid
i、激活swap裝置
j、加載額外裝置的驅動程式
k、清理操作
3、服務的啟停
系統初始化之後,系統就可以使用了,但是往往還需要啟動一些相應的服務來使用網絡或主機功能。此時/sbin/init程式會讀取/etc/rc.d/rc檔案并根據運作級别來判斷停止某些服務并啟動某些服務。S
需要啟停的服務腳本都存放于/etc/rc$runlevel.d/目錄下,其中K開頭的腳本為要關閉的服務腳本,K後面的數字越小,優先級越高,需先關閉。而S開頭的腳本為要開啟的服務腳本,S後面的數字越小,優先級越高,需先啟動。實際上,所有/etc/rc$runlevel.d/目錄下的腳本均為/etc/init.d/目錄下的腳本連結。
4、啟動終端
在啟動所有需要的服務後,系統會啟動終端或圖形終端來等待使用者登入。至此,整個系統啟動流程就結束了。
5、執行使用者自定義引導程式/etc/rc.d/rc.local。其實當執行/etc/rc.d/rc3.d/S99local時,它就是在執行/etc/rc.d/rc.local。S99local是指向rc.local的符号連結。就是一般來說,自定義的程式不需要執行上面所說的繁瑣的建立shell增加連結檔案的步驟,隻需要将指令放在rc.local裡面就可以了,這個shell腳本就是保留給使用者自定義啟動内容的。
六、總結
簡要流程:
POST-->BootSequence(啟動順序)-->BootLoader(MBR,grub)-->Kennel(initrd)-->rootfs(readonly)-->switchroot-->/sbin/init-->設定預設運作級别-->運作系統初始化腳本,完成系統初始化-->關閉對應級别下需要停止的服務,啟動對應級别下需要開啟的服務-->設定登入終端[-->啟動圖形終端]
參考:www.magedu.com
http://blog.chinaunix.net/uid-23069658-id-3142047.html
http://www.linuxidc.com/Linux/2014-03/97862.htm