開機不是只要單擊電源鈕,而關機只要關掉電源鈕就可以了嗎?話是這樣沒錯啦,但是由于 Linux 是一套多人多任務的操作系統,你難保你在關機時沒有人在在線,如果你關機的時候碰巧一大群人在在線工作, 那會讓當時在在線工作的人馬上斷線的!那不是害死人了!一些數據可是無價之寶。
另外 Linux 在執行的時候,雖然你在畫面上叧會看到黑壓壓的一片,完全沒有任何畫面, 但其實他是有很多的程序在背景底下執行的,例如登錄文件管控程序、例行性工作排程等, 當然還有一大堆網絡服務,如郵件服務器、WWW服務器等等。你如果隨便關機的話, 是很容易傷害硬盤及數據傳輸的操作!所以在 Linux 下開機關機可是一門大學問。
Linux的組成為: kernel + rootfs
kernel: 進程管理、內存管理、網絡管理、驅動程序、文件系統、安全功能
rootfs: 程序和glibc
庫:函數集合, function, 調用接口(頭文件負責描述)
過程調用:procedure,無返回值
函數調用:function
程序:二進制執行文件
內核設計流派:
單內核(monolithic kernel):Linux
把所有功能集成于同一個程序
微內核(micro kernel):Windows, Solaris
每種功能使用一個單獨子系統實現
Linux內核特點:
支持模塊化:.ko(內核對象)
如:文件系統,硬件驅動,網絡協議等
支持內核模塊的動態裝載和卸載
組成部分:
核心文件:/boot/vmlinuz-VERSION-release
ramdisk:輔助的偽根系統
CentOS 5: /boot/initrd-VERSION-release.img
CentOS6,7: /boot/initramfs-VERSION-release.img
模塊文件:/lib/modules/VERSION-release
既然啟動是一件嚴肅的事情,那我們就一起來了解一下啟動的過程:
系統啟動過程簡介:
1、加載BIOS的硬件信息與進行自我檢測,并依據設置取得第一個可啟動的設備;
2、讀取并執行第一個啟動設備內的MBR的 boot loader (既是grub,spfdisk等程序);
3、依據boot loader的設置加載Kernel, kernel會開始檢測硬件與加載驅動程序;
4、在硬件驅動成功后,Kernel會主動調動init進程,而init會取得run-level信息;
5、init執行/etc/rc.d/rc.sysinit文件來準備軟件執行的操作環境(如網絡、時區等);
6、init執行run-level的各個服務的啟動(script方式);
7、init執行/etc/rc.d/rc.local文件;
8、init執行終端機模擬程序mingetty來啟動login程序,最后等待用戶登錄。
詳細說明:
1、加載BIOS的硬件信息與進行自我檢測,并依據設置取得第一個可啟動的設備;
啟動系統首先就要加載BIOS,并通過BIOS加載CMOS的信息,然后通過CMOS內的設置取得主機的各項硬件配置信息。
然后進行開機自檢POST(Power-on Self Test)。開始執行硬件檢測的初始化。接下來就開始啟動設備的數據讀取。
POST:Power-On-Self-Test,加電自檢,是BIOS功能的一個主要部分。負責完成對CPU、主板、內存、硬盤子系統、顯示子系統、串并行接口、鍵盤、CD-ROM光驅等硬件情況的檢測。
ROM:BIOS(Basic Input and Output System),保存著有關計算機系統最重要的基本輸入輸出程序,系統信息設置、開機加電自檢程序和系統啟動自舉程序等。
RAM:CMOS互補金屬氧化物半導體,保存各項參數的設定,按次序查找引導設備,第一個有引導程序的設備為本次啟動設備
2、讀取并執行第一個啟動設備內的MBR的 boot loader
因為系統軟件都存放在硬盤當中,所以BIOS會指定啟動的設備,讓我們可以讀取到系統的內核文件,由于不同的操作系統的文件系統格式不同,所以必須要以一個引導裝載程序來處理內核文件的加載問題。這個程序就被成為boot loader。而boot loader程序就安裝在啟動設別的第一個扇區內,也就是MBR內。
思考:這里有一個有趣的問題:
既然內核文件需要loader來讀取,每個操作系統的loader都不相同,那么BIOS是怎么找到MBR內的loader呢?
其實BIOS是通過硬件的INT 13 中斷功能來讀取MBR的,只要BIOS可以檢測到你的磁盤,那么他就可以通過INT 13 來讀取該磁盤中第一個扇區內的MBR中的信息,這樣就可以執行boot loader了。
bootloader: 引導加載器,引導程序
①提供菜單,用戶可以選擇不同的啟動項,這也是多重引導的重要功能;
②加載內核文件:直接指向可啟動的程序區段來開始啟動操作系統;
③轉交其他的loader:將引導程序轉交給其他的loader來執行;
因為具有菜單的功能,所以我們可以現在不同的內核來啟動系統;也因為具有轉交給其他的loader的功能,所以可以實現,一機多系統。
但是:
windows: ntloader,僅是啟動OS ;windows默認沒有控制權轉交的功能,
Linux:功能豐富,提供菜單,允許用戶選擇要啟動系統或不同的內核版本;把用戶選定的內核裝載到內存中的特定空間中,解壓、展開,并把系統控制權移交給內核
所以,要實現多系統,只能先裝windows,再裝linux,因為linux可以把引導轉載程序的控制權交給windows來管理。此時的windows的loader就會接管啟動流程,這樣就可以加載內核文件了。
3、依據boot loader的設置加載Kernel, kernel會開始檢測硬件與加載驅動程序;
linux會將內核解壓縮到內存中,并且利用內核的功能來開始測試與驅動各個周邊的設備,包括CPU,存儲設備,網卡等。同時內核也會對自己的功能重新檢測一下硬件。而不一定會使用BIOS檢測到的硬件信息,也就是說,從此時開始內核開始完全接管BIOS后的工作。
那么內核文件存放在哪里呢?
一般來說內核文件存放在/boot下,并且取名為vmlinuz
-
config-2.6.32-642.el6.x86_64 :此版本內核被編譯時選擇的功能和模塊配置文件;
-
grub:引導裝載程序 grub 相關數據目錄
-
System.map-2.6.32-642.el6.x86_64:內核功能放置到內存地址的對應表
-
initramfs-2.6.32-642.el6.x86_64.img:虛擬文件系統文件
-
vmlinuz-2.6.32-642.el6.x86_64:內核文件!
根據這些文件的名字,我們也可以知道此版本的linux內核為2.6.32-642.el6.x86_64這個版本,因為linux內核是可以通過動態加載內核模塊的(即驅動程序),這些模塊存放在/lib/modules/目錄內。由于模塊放置在磁盤根目錄內,因此在啟動的過程中內核必須要掛載根目錄,這樣才能讀取到內核模塊提供的加載驅動程序的功能。
為了防止影響到磁盤內文件系統,因此啟動的過程中根目錄是以只讀的形式掛載的。
bootloader是系統的啟動加載器。通常情況下,引導程序都安裝在bootloader中。以我們常見的grup為例,grub分為stage1,stage1.5,stage2。其中stage1的代碼是直接存放在mbr中的。當BIOS將控制權傳遞給MBR后,stage1的代碼就開始運行,它主要負責將stage1.5或者stage2的內容加載在內存中。stage2被加載到內存中后,就會讀取grub的配置文件grub.conf
思考: 現在就遇到一個問題,內核并不認識設備,所以需要去加載驅動程序,但是驅動程序都在/lib/modules/目錄內,而根目錄現在根本就沒辦法掛載,那是怎么讀取到/lib/modules/目錄內的驅動程序的?
在這種情況下,linux系統是依靠虛擬文件系統來解決這個問題的,
虛擬文件系統(initialRAM disk):
一般文件名為:"/boot/initramfs-版本號.img" 這個文件能夠通過boot loader加載到內存中,然后被仿真成一個根目錄,且仿真文件系統內有一個可執行的程序,可以通過該程序加載啟動過程中最需要的內核模塊,通常這些模塊就是RAID,LVM等文件系統與磁盤接口的驅動程序。載入完成之后,會幫助內核重新調用/sbin/init/來開始后續的流程。。。
系統初始化過程:
POST –> BootSequence(BIOS) –> Bootloader(MBR) –> kernel(ramdisk) –> rootfs(只讀) –> init(systemd)
4、在硬件驅動成功后,Kernel會主動調動init進程,而init會取得run-level信息;
加載完畢后,內核會主動調用第一個進程,“/sbin/init”,它的功能就是準備軟件執行的環境。所有的操作都會通過init的配置文件即/etc/inittab來規劃,而inittab中有一個很重要的設置選項,那就是默認的run level(運行級別)。
運行級別:為系統運行或維護等目的而設定;0-6:7個級別
0:關機
1:單用戶模式(root自動登錄), single, 維護模式
2: 多用戶模式,啟動網絡功能,但不會啟動NFS;維護模式
3:多用戶模式,正常模式;文本界面
4:預留級別;可同3級別
5:多用戶模式,正常模式;圖形界面
6:重啟
默認級別:3, 5
切換級別:init #
查看級別:runlevel; who -r
init讀取其初始化文件:/etc/inittab
初始運行級別(RUN LEVEL)
系統初始化腳本
對應運行級別的腳本目錄
捕獲某個關鍵字順序
定義UPS電源終端/恢復腳本
在虛擬控制臺生成getty
在運行級別5初始化X
5、init執行/etc/rc.d/rc.sysinit文件來準備軟件執行的操作環境(如網絡、時區等);
/etc/inittab文件中有這一句“ si::sysinit:/etc/rc.d/rc.sysinit ” 這表示:開始加載各項系統服務之前,得先做好整個系統環境,主要利用 /etc/rc.d/rc.sysinit 這腳本來設置好系統環境的,所以,想要知道到底 CentOS 開機的過程當中做什么動作,就得要仔細的分析 /etc/rc.d/rc.sysinit這個文件
/etc/rc.d/rc.sysinit: 系統初始化腳本
(1) 設置主機名
(2) 設置歡迎信息
(3) 激活udev和selinux
(4) 掛載/etc/fstab文件中定義的文件系統
(5) 檢測根文件系統,并以讀寫方式重新掛載根文件系統
(6) 設置系統時鐘
(7) 激活swap設備
(8) 根據/etc/sysctl.conf文件設置內核參數
(9) 激活lvm及software raid設備
(10) 加載額外設備的驅動程序
(11) 清理操作
6、init執行run-level的各個服務的啟動(script方式);
加載內核讓整個系統準備接受指令來工作,再經過 /etc/rc.d/rc.sysinit 的系統模塊與相關硬件信息的初始化后,你的 CentOS 系統應該已經順利工作了。
只是,我們還需要啟動系統所需要的各項服務,這樣主機才能提供相關的網絡或者是主機功能。這個時候,依據在 /etc/inittab 里面提到的 run level 設定值,就可以來決定啟動的服務項目了。
舉例來說,使用 run level 3 當然就不需要啟動X Window 的相關服務。
各個不同的 run level 服務啟動的各個腳本地址存放在“/etc/inittab”里;
說明:rcN –> 意味著讀取/etc/rc.d/rcN.d/
K*: K##*:##運行次序;數字越小,越先運行;數字越小的服務,通常為依賴到別的服務
S*: S##*:##運行次序;數字越小,越先運行;數字越小的服務,通常為被依賴到的服務
for srvin /etc/rc.d/rcN.d/K*; do $srv stop done
for srvin /etc/rc.d/rcN.d/S*; do $srv start done
7、init執行/etc/rc.d/rc.local文件;
在完成默認 runlevel 指定的各項服務后,如果還有其他的動作想要完成時,這個檔案就可以執行自己想要執行的系統指令了。 也就是說,有任何想要在開機時就進行的工作時,直接將他寫入 /etc/rc.d/rc.local , 那么該工作就會在開機的時候自動被加載。而不必等登入系統去啟動。
注意:正常級別下,最后啟動一個服務S99local沒有鏈接至/etc/rc.d/init.d一個服務腳本,而是指向/etc/rc.d/rc.local腳本
不便或不需寫為服務腳本放置于/etc/rc.d/init.d/目錄,且又想開機時自動運行的命令,可直接放置于/etc/rc.d/rc.local文件中
/etc/rc.d/rc.local在指定運行級別腳本后運行
可以根據情況,進行自定義修改
8、init執行終端機模擬程序mingetty來啟動login程序,最后等待用戶登錄。
在完成了系統所有服務的啟動后,接下來 Linux 就會啟動終端機或者是 X Window 來等待使用者登入啦! 實際參考的項目是 /etc/inittab 內的這一段:
這一段代表,在 run level 2, 3, 4, 5 時,都會執行 /sbin/mingetty , 而且執行六個,這也是為何我們 Linux 會提供”六個純文本終端機“的設定所在。 因為 mingetty 就是在啟動終端機的命令。
要注意的是那個 respawn 的 init 操項目,他代表當后面的指令被終止 (terminal) 時, init 會主動的重新啟動該項目。這也是為何我們登入 tty1 終端機接口后,以 exit 離開后, 系統還是會重新顯示等待用戶輸入的畫面的原因。
如果我們使用的是 run level 5 那么除了這六個終端機之外, init 還會執行 /etc/X11/prefdm -nodaemon 那個指令, 他主要的功能就是在啟動 X Window 。
CentOS 6啟動流程:
POST –> Boot Sequence(BIOS) –> Boot Loader –> Kernel(ramdisk) –> rootfs–> switchroot–> /sbin/init–>(/etc/inittab, /etc/init/*.conf) –> 設定默認運行級別–> 系統初始化腳本rc.sysinit–> 關閉或啟動對應級別的服務–> 啟動終端
簡單圖示即為:
原創文章,作者:Groot,如若轉載,請注明出處:http://www.www58058.com/47689
文章理論部分闡述的很直觀明了,讓人能一目了然,通讀全文,能讓人對開機啟動流程有一個深入的了解,受教了。