Linux启动流程

过程一览
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 檔案;
9、init 執行終端機模擬程式 mingetty 來啟動 login 程式,最後就等待使用者登入啦;


第一支程式 init 及設定檔 /etc/inittab 與 runlevel
在核心載入完畢、進行完硬體偵測與驅動程式載入後,此時你的主機硬體應該已經準備就緒了 (ready) , 此時核心會主動的呼叫第一支程式,那就是 /sbin/init 囉。你會發現 init 的 PID 號碼是一號。 /sbin/init 最主要的功能就是準備軟體執行的環境,包括系統的主機名稱、網路設定、語系處理、檔案系統格式及其他服務的啟動等。 而所有的動作都會透過 init 的設定檔,亦即是 /etc/inittab 來規劃,而 inittab 內還有一個很重要的設定項目,那就是預設的 runlevel (開機執行等級) 啦!


Run level:執行等級有哪些?

那麼什麼是 run level 呢?他有什麼功用啊?其實很簡單啦, Linux 就是藉由設定 run level 來規定系統使用不同的服務來啟動,讓 Linux 的使用環境不同。基本上,依據有無網路與有無 X Window 而將 run level 分為 7 個等級,分別是:

0 – halt (系統直接關機)
1 – single user mode (單人維護模式,用在系統出問題時的維護)
2 – Multi-user, without NFS (類似底下的 runlevel 3,但無 NFS 服務)
3 – Full multi-user mode (完整含有網路功能的純文字模式)
4 – unused (系統保留功能)
5 – X11 (與 runlevel 3 類似,但加載使用 X Window)
6 – reboot (重新開機)

由於 run level 0, 4, 6 不是關機、重新開機就是系統保留的,所以:『 您當然不能將預設的 run level 設定為這三個值 』, 否則系統就會不斷的自動關機或自動重新開機…. 好了,那麼我們開機時,到底是如何取得系統的 run level 的?當然是 /etc/inittab 所設定的囉! 那麼 /etc/inittab 到底有什麼資訊呢?我們先來看看這個檔案的內容好了:


/etc/inittab 的內容與語法
[root@www ~]# vim /etc/inittab
id:5:initdefault:

si::sysinit:/etc/rc.d/rc.sysinit

# 7 個不同 run level 的,需要啟動的服務的 scripts 放置路徑:

l0:0:wait:/etc/rc.d/rc 0l1:1:wait:/etc/rc.d/rc 1l2:2:wait:/etc/rc.d/rc 2l3:3:wait:/etc/rc.d/rc 3l4:4:wait:/etc/rc.d/rc 4l5:5:wait:/etc/rc.d/rc 5l6:6:wait:/etc/rc.d/rc 6

# 是否允許按下 [ctrl]+[alt]+[del] 就重新開機的設定項目:
ca::ctrlaltdel:/sbin/shutdown -t3 -r now

# 底下兩個設定則是關於不斷電系統的 (UPS),一個是沒電力時的關機,一個是復電的處理
pf::powerfail:/sbin/shutdown -f -h +2 “Power Failure; System Shutting Down”
pr:12345:powerokwait:/sbin/shutdown -c “Power Restored; Shutdown Cancelled”

1:2345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6

x:5:respawn:/etc/X11/prefdm -nodaemon

讓我們解析一下這個檔案吧!首先,這個檔案的語法是利用冒號 (:) 將設定分隔成為四個欄位,每個欄位的意義與說明如下:

[設定項目]:[run level]:[init 的動作行為]:[指令項目]

設定項目:最多四個字元,代表 init 的主要工作項目,只是一個簡單的代表說明。
run level:該項目在哪些 run level 底下進行的意思。如果是 35 則代表 runlevel 3 與 5 都會執行。
init 的動作項目:主要可以進行的動作項目意義有:inittab 設定值 意義說明

initdefault 代表預設的 run level 設定值
sysinit 代表系統初始化的動作項目
ctrlaltdel 代表 [ctrl]+[alt]+[del] 三個按鍵是否可以重新開機的設定
wait 代表後面欄位設定的指令項目必須要執行完畢才能繼續底下其他的動作
respawn 代表後面欄位的指令可以無限制的再生 (重新啟動)。舉例來說, tty1 的 mingetty 產生的可登入畫面, 在你登出而結束後,系統會再開一個新的可登入畫面等待下一個登入。

更多的設定項目請參考 man inittab 的說明。
指令項目:亦即應該可以進行的指令,通常是一些 script 囉。



init 的處理流程

事實上 /etc/inittab 的設定也有點類似 shell script 啦,因為該檔案內容的設定也是一行一行的從上往下處理的, 因此我們可以知道 CentOS 的 init 依據 inittab 設定的處理流程會是:

先取得 runlevel 亦即預設執行等級的相關等級 (以鳥哥的測試機為例,為 5 號);
使用 /etc/rc.d/rc.sysinit 進行系統初始化
由於 runlevel 是 5 ,因此只進行『l5:5:wait:/etc/rc.d/rc 5』,其他行則略過
設定好 [ctrl]+[alt]+[del] 這組的組合鍵功能
設定不斷電系統的 pf, pr 兩種機制;
啟動 mingetty 的六個終端機 (tty1 ~ tty6)
最終以 /etc/X11/perfdm -nodaemon 啟動圖形介面啦!

現在你可以知道為啥 [ctrl]+[alt]+[del] 可以重新開機而我們預設提供 6 個虛擬終端機 (tty1~tty6) 給你使用了吧!由於整個設定都是依據 /etc/inittab 來決定的,因此如果你想要修改任何細節的話, 可以這樣做喔:

如果不想讓使用者利用 [crtl]+[alt]+[del] 來重新啟動系統,可以將『 ca::ctrlaltdel:/sbin/shutdown -t3 -r now 』加上註解 (#) 來取消該設定

規定開機的預設 run level 是純文字的 3 號或者是具有圖形介面的 5 號 ,可經由 『 id:5:initdefault: 』那個數字來決定! 以鳥哥自己這個檔案為例,我是使用預設的圖形介面。如果你想要關閉圖形介面的話,將該行 5 改成 3 即可。

如果不想要啟動六個終端機 (tty1~tty6),那麼可以將『 6:2345:respawn:/sbin/mingetty tty6』關閉數個。但務必至少啟動一個喔!

所以說,你現在會自行修改登入時的預設 run level 設定值了嗎?夠簡單的吧? 一般來說,我們預設都是 3 或者是 5 來作為預設的 run level 的。但有時後可能需要進入 run level 1, 也就是單人維護模式的環境當中。這個 run level 1 有點像是 Windows 系統當中的『安全模式』啦, 專門用來處理當系統有問題時的操作環境。此外,當系統發現有問題時,舉例來說,不正常關機造成 filesystem 的不一致現象時,系統會主動的進入單人維護模式呢!

好了, init 在取得 run level 之後,接下來要幹嘛? 上面 /etc/inittab 檔案內容不是有提到 sysinit 嗎?準備初始化系統了吧!


init 處理系統初始化流程 (/etc/rc.d/rc.sysinit)

還記得上面提到 /etc/inittab 裡頭有這一句『 si::sysinit:/etc/rc.d/rc.sysinit 』吧? 這表示:『我開始載入各項系統服務之前,得先做好整個系統環境,我主要利用 /etc/rc.d/rc.sysinit 這個 shell script 來設定好我的系統環境的。』夠清楚了吧? 所以,我想要知道到底 CentOS 開機的過程當中幫我進行了什麼動作,就得要仔細的分析 /etc/rc.d/rc.sysinit 囉。Tips:

老實說,這個檔案的檔名在各不同的 distributions 當中都不相同, 例如 SuSE server 9 就使用 /etc/init.d/boot 與 /etc/init.d/rc 來進行的。 所以,你最好還是自行到 /etc/inittab 去察看一下系統的工作喔! ^_^

如果你使用 vim 去查閱過 /etc/rc.d/rc.sysinit 的話,那麼可以發現他主要的工作大抵有這幾項:

取得網路環境與主機類型:
讀取網路設定檔 /etc/sysconfig/network ,取得主機名稱與預設通訊閘 (gateway) 等網路環境。
測試與掛載記憶體裝置 /proc 及 USB 裝置 /sys:
除掛載記憶體裝置 /proc 之外,還會主動偵測系統上是否具有 usb 的裝置, 若有則會主動載入 usb 的驅動程式,並且嘗試掛載 usb 的檔案系統。
決定是否啟動 SELinux :
我們在第十七章談到的 SELinux 在此時進行一些檢測, 並且檢測是否需要幫所有的檔案重新編寫標準的 SELinux 類型 (auto relabel)。
啟動系統的亂數產生器
亂數產生器可以幫助系統進行一些密碼加密演算的功能,在此需要啟動兩次亂數產生器。
設定終端機 (console) 字形:
設定顯示於開機過程中的歡迎畫面 (text banner);
設定系統時間 (clock) 與時區設定:需讀入 /etc/sysconfig/clock 設定值
周邊設備的偵測與 Plug and Play (PnP) 參數的測試:
根據核心在開機時偵測的結果 (/proc/sys/kernel/modprobe ) 開始進行 ide / scsi / 網路 / 音效 等周邊設備的偵測,以及利用以載入的核心模組進行 PnP 裝置的參數測試。
使用者自訂模組的載入
使用者可以在 /etc/sysconfig/modules/*.modules 加入自訂的模組,則此時會被載入到系統當中
載入核心的相關設定:
系統會主動去讀取 /etc/sysctl.conf 這個檔案的設定值,使核心功能成為我們想要的樣子。
設定主機名稱與初始化電源管理模組 (ACPI)
初始化軟體磁碟陣列:主要是透過 /etc/mdadm.conf 來設定好的。
初始化 LVM 的檔案系統功能
以 fsck 檢驗磁碟檔案系統:會進行 filesystem check
進行磁碟配額 quota 的轉換 (非必要):
重新以可讀寫模式掛載系統磁碟:
啟動 quota 功能:所以我們不需要自訂 quotaon 的動作
啟動系統虛擬亂數產生器 (pseudo-random):
清除開機過程當中的暫存檔案:
將開機相關資訊載入 /var/log/dmesg 檔案中。

在 /etc/rc.d/rc.sysinit 將基本的系統設定資料都寫好了,也將系統的資料設定完整! 而如果你想要知道到底開機的過程中發生了什麼事情呢?那麼就執行『 dmesg 』吧。 另外,基本上,在這個檔案當中所進行的很多工作的預設設定檔,其實都在 /etc/sysconfig/ 當中呢! 所以,請記得將 /etc/sysconfig/ 內的檔案好好的瞧一瞧喔! ^_^

在這個過程當中,比較值得注意的是自訂模組的載入!在 CentOS 當中,如果我們想要載入核心模組的話, 可以將整個模組寫入到 /etc/sysconfig/modules/*.modules 當中,在該目錄下, 只要記得檔名最後是以 .modules 結尾即可。 這個過程是非必要的,因為我們目前的預設模組實在已經很夠用了,除非是您的主機硬體實在太新了, 非要自己載入新的模組不可,否則,在經過 /etc/rc.d/rc.sysinit 的處理後, 你的主機系統應該是已經跑得很順暢了啦!就等著你將系統相關的服務與網路服務啟動囉!


啟動系統服務與相關啟動設定檔 (/etc/rc.d/rc N & /etc/sysconfig)

載入核心讓整個系統準備接受指令來工作,再經過 /etc/rc.d/rc.sysinit 的系統模組與相關硬體資訊的初始化後,你的 CentOS 系統應該已經順利工作了。 只是,我們還得要啟動系統所需要的各項『服務』啊!這樣主機才能提供我們相關的網路或者是主機功能嘛! 這個時候,依據我們在 /etc/inittab 裡面提到的 run level 設定值,就可以來決定啟動的服務項目了。 舉例來說,使用 run level 3 當然就不需要啟動 X Window 的相關服務囉,您說是吧?

那麼各個不同的 run level 服務啟動的各個 shell script 放在哪?還記得 /etc/inittab 裡面提到的:l0:0:wait:/etc/rc.d/rc 0

l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5 l6:6:wait:/etc/rc.d/rc 6

上面提到的就是各個 run level 要執行的各項腳本放置處啦!主要是透過 /etc/rc.d/rc 這個指令來處理相關任務! 由於鳥哥使用預設的 runlevel 5 ,因此我們主要針對上述特殊字體那行來解釋好了: /etc/rc.d/rc 5 的意義是這樣的 (建議您自行使用 vim 去觀察一下 /etc/rc.d/rc 這個檔案,你會更有概念!):

透過外部第一號參數 ($1) 來取得想要執行的腳本目錄。亦即由 /etc/rc.d/rc 5 可以取得 /etc/rc5.d/ 這個目錄來準備處理相關的腳本程式;
找到 /etc/rc5.d/K??* 開頭的檔案,並進行『 /etc/rc5.d/K??* stop 』的動作;
找到 /etc/rc5.d/S??* 開頭的檔案,並進行『 /etc/rc5.d/S??* start 』的動作;

透過上面的說明我們可以知道所有的項目都與 /etc/rc5.d/ 有關,那麼我們就來瞧瞧這個目錄下有些什麼玩意兒吧![root@www ~]# ll /etc/rc5.d/

lrwxrwxrwx 1 root root 16 Sep 4 2008 K02dhcdbd -> ../init.d/dhcdbd
….(中間省略)….
lrwxrwxrwx 1 root root 14 Sep 4 2008 K91capi -> ../init.d/capi
lrwxrwxrwx 1 root root 23 Sep 4 2008 S00microcode_ctl -> ../init.d/microcode_ctl
lrwxrwxrwx 1 root root 22 Sep 4 2008 S02lvm2-monitor -> ../init.d/lvm2-monitor
….(中間省略)….
lrwxrwxrwx 1 root root 17 Sep 4 2008 S10network -> ../init.d/network
….(中間省略)….
lrwxrwxrwx 1 root root 11 Sep 4 2008 S99local -> ../rc.local
lrwxrwxrwx 1 root root 16 Sep 4 2008 S99smartd -> ../init.d/smartd
….(底下省略)….

在這個目錄下的檔案很有趣,主要具有幾個特點:

檔名全部以 Sxx 或 Kxx ,其中 xx 為數字,且這些數字在檔案之間是有相關性的!
全部是連結檔,連結到 stand alone 服務啟動的目錄 /etc/init.d/ 去

我們在第十八章談過服務的啟動主要是以『/etc/init.d/服務檔名 {start,stop}』來啟動與關閉的,那麼透過剛剛 /etc/rc.d/rc 程式的解說,我們可以清楚的瞭解到了 /etc/rc5.d/[SK]xx 其實就是跑到 /etc/init.d/ 去找到相對應的服務腳本, 然後分別進行 start (Sxx) 或 stop (Kxx) 的動作而已啦!舉例來說,以上述的表格內的 K91capi 及 S10network 為例好了, 透過 /etc/rc.d/rc 5 的執行,這兩個檔案會這樣進行:

/etc/rc5.d/K91capi stop –> /etc/init.d/capi stop
/etc/rc5.d/S10network start –> /etc/init.d/network start

所以說,你有想要啟動該 runlevel 時就執行的服務,那麼利用 Sxx 並指向 /etc/init.d/ 的特定服務啟動腳本後, 該服務就能夠在開機時啟動啦!就這麼簡單!問題是,你需要自行處理這個 K, S 開頭的連結檔嗎? 並不需要的,第十八章談到的 chkconfig 就是在負責處理這個連結檔啦!這樣有沒有跟第十八章的觀念串在一起了呢? ^_^

那麼為什麼 K 與 S 後面要有數字呢?因為各不同的服務其實還是互有關係的。舉例來說,如果要啟動 WWW 服務,總是得要有網路吧?所以 /etc/init.d/network 就會比較先被啟動啦!那麼您就會知道在 S 或者是 K 後面接的數字是啥意思了吧?嘿嘿,那就是執行的順序啦!那麼哪個檔案被最後執行呢? 看到最後一個被執行的項目是啥?沒錯,就是 S99local ,亦即是: /etc/rc.d/rc.local 這個檔案啦!

如果想要将一个服务启动成为系统服务.可以在/etc/init.d/下建立一个脚本,或者是脚本链接档. 然后就可以用chkconfig –add 加入服务,同时设置在启动等级中是否启动这样,会自动将其加入到/etc/rc[0-6].d下.


使用者自訂開機啟動程序 (/etc/rc.d/rc.local)

在完成預設 runlevel 指定的各項服務的啟動後,如果我還有其他的動作想要完成時,舉例來說, 我還想要寄一封 mail 給某個系統管理帳號,通知他,系統剛剛重新開機完畢,那麼是否應該要製作一個 shell script 放置在 /etc/init.d/ 裡面,然後再以連結方式連結到 /etc/rc5.d/ 裡面呢?呵呵!當然不需要!還記得上一小節提到的 /etc/rc.d/rc.local 吧? 這個檔案就可以執行您自己想要執行的系統指令了。

也就是說,我有任何想要在開機時就進行的工作時,直接將他寫入 /etc/rc.d/rc.local , 那麼該工作就會在開機的時候自動被載入喔!而不必等我們登入系統去啟動呢! 是否很方便啊!一般來說,鳥哥就很喜歡把自己製作的 shell script 完整檔名寫入 /etc/rc.d/rc.local ,如此一來,開機就會將我的 shell script 執行過,真是好棒那!

echo “/usr/local/mysql/bin/mysqld_safe –user=root &” >> /etc/rc.local

原文地址:https://www.cnblogs.com/dieangel/p/3326954.html