CentOS系統啟動流程(上)
作為系統運維人員,詳細的了解操作系統的啟動流程,對于我們日常排除故障大有益處,遇到相關的問題處理,能快速定位,迅速鎖定關鍵點。
下面詳細介紹一下,CentOS系統的啟動過程,以供各位參考。由于linux各個發行版使用的啟動方法略有不同,比如CentOS5使用的是initd,CentOS6使用的是較為接近的Upstart,而CentOS7則是使用畫風完全不同的Systemd,因而,對于其中有區別的部分,我也會對應不同的發行版本來分別介紹。
一個基本的操作系統,無非就是由內核+系統級別的庫+應用程序所組成。其中,內核負責進行內存管理、進程管理、安全管理、網絡管理以及硬件驅動程序的管理。庫提供了上層應用程序向下層操作系統的調用接口。應用程序,顧名思義,就是能提供各種功能各種服務的軟件了。這其中,內核是整個系統的根本,沒有內核,則應用程序也無法單獨存在。因而,每個操作系統,內核是必不可少的,想要使用電腦,則必需先啟動內核。因而,操作系統的啟動,實際上也就是內核啟動的過程。
回到正題,一般操作系統啟動的過程,大致可分為以下幾個步驟:
加電自檢(POST)–>BootLoader選擇引導的內核–>內核啟動,建立內核空間–>加載根文件系統–>建立用戶空間,并啟動用戶空間的第一個程序,然后創建交互式接口,等待用戶的操作指令
加電自檢(POST):
通過固化在主板上CMOS的ROM芯片,執行指定程序,進行硬件檢測。該步驟主要檢查硬件幾大部件,CPU、主板、內存、顯卡等設備,維持計算機運行的主要部件。如設備有問題,自檢不通過,設備也點不亮。當然,也會順帶檢測其它一些非必要的硬件設備,比如外設:鼠標鍵盤網卡聲卡等。
BootLoader:
BIOS(Basic Input and Output System)設置里,有個選項是關于引導順序(BOOT Sequence)的,加電自檢完成后,系統會根據BOOT Sequence里設定的順序,查找可用的MBR(主引導記錄),一旦找到設備有MBR(就是第一個找到的MBR設備),則會選擇從該設備引導系統。MBR記錄中,有bootloader程序,大小為446字節,該部分記錄了引導系統的重要信息。該程序的主要功能,是提供一個菜單,允許用戶選擇要啟動的系統或不同的內核版本,把用戶選定的內核裝載到內存中的特定空間中,解壓、展開,并把系統控制權移交給內核,從而完成內核的引導。
這里插入一段小插曲,以前比較老的系統,BootLoader的任務由LILO(LInux LOader)的軟件所承擔,而該軟件也能很好的完成它的任務。因為以前的硬盤容量都比較小,因而446字節的信息描述足以完成對內核的加載。而隨著現今硬盤容量的激增,每個分區都很大,而內核程序有可以保存在每一個分區中,這樣,對于大容量硬盤,LILO則顯得有點力不從心了。不過Linux界從來都不缺明星呀,新一代的BootLoader軟件–GRUB: GRand Unified Bootloader (GRUB)閃亮登場。
GRUB傳統版本用于CentOS5、6,版本號是0.X,新的CentOS7則升級到1.X版本。GRUB采用了分階段運行的方式,成功的繞開了446字節的限制,實現了對大容量硬盤的支持。第1階段,GRUB依然是駐留在MBR的bootloader中,這一階段的BRUB,主要完成對內核所在設備的鏈接,找到內核駐留到的存儲設備。然后,GRUB有個過渡階段,可稱為1.5階段吧,該階段利用找到的存儲設備上的文件,識別內核所在硬盤分區上的文件系統,加載內核所在設備的驅動程序。能識別內核所在硬盤分區的文件系統,事情就好辦了,第2階段,將內核加載到內存的特定位置,運行,并將系統的控制權移交到該內核。至此,內核完成加載并開始啟動。
內核啟動,建立內核空間,加載根文件系統–,建立用戶空間:
Kernel啟動后,會進行以下操作:
自身初始化;
探測可識別到的所有硬件設備;
加載硬件驅動程序:(有可能會借助于ramdisk加載驅動);
以只讀方式掛載根文件系統;
運行用戶空間的第一個應用程序;
其中用戶空間的第一個應用程序的創建,各個發行版本因應使用的技術,在實現上略有不同,在CentOS5上沿用的是sysv風格的initd;而CentOS6使用的是在initd升級改良而來的Upstart;CentOS7,則采用了全新的systemd技術。鑒于CentOS5與 CentOS6采用的技術較為雷同,在此,以CentOS5所使用的initd進行講解,至于CentOS7所使用的systemd技術,我會在下篇中說明,在這里先賣個小廣告,敬請大家期待。
CentOS5運行用戶空間的第一個應用程序是 /sbin/init,init以守護進程的形式而存在,且是所有用戶空間進程的父進程,所有用戶空間進程均由init進程創建派生而來。同時,在init運行的同時,init會利用腳本程序,對系統環境進行大量的操作,以便完成系統初始化。
對于系統初始化,我們特別定制了一個特殊的腳本:/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)清理操作
然后,CentOS有個運行級別的概念。什么是運行級別呢?運行級別就是為了系統的運行或維護等應用目的而設定的運行等級。
CentOS5/6有7個運行級別,分別是:
0:關機
1:單用戶模式(root,無須登錄,無需密碼),single,維護模式
2:多用戶模式,會啟動網絡功能,但不會啟動NFS:維護模式
3:多用戶模式,正常模式,文本界面
4:預留級別,暫不使用,但可視為同3級別一樣
5:多用戶模式,正常模式,圖形界面
6:重啟系統
其中,默認級別是級別3 或級別5
Init程序運行時,會讀取 /etc/inittab的配置文件,根據配置文件的不同而執行相應的動作。這里貼出一個inittab配置文件的例子:
[root@www ~]# cat /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:
文件前面的都是注釋說明,實際只有一行,即最后一行是實際配置。它的格式為:
id:runlevel:action:process
其中:
Id:就是每行的id值,不重復即可;
Runlevel:就是上面提到的運行級別的數值;
Action:action分別有如下的動作:
wait:切換至此級別運行一次
respawn:此process終止,就重新啟動之
initdefault:設定默認運行級別, process省略
sysinit:設定系統初始化方式,此處一般為指定/etc/rc.d/rc.sysint;
上面例子中的:id:3:initdefault: #就是默認運行3級別的意思
劃分了運行級別,到底有什么作用呢?讓我們看看/etc/rc.d目錄下的內容:
[root@www /]# ls -lh /etc/rc.d
total 60K
drwxr-xr-x. 2 root root 4.0K Apr 7 18:52 init.d
-rwxr-xr-x. 1 root root 2.6K Oct 16 2014 rc
drwxr-xr-x. 2 root root 4.0K Apr 7 18:53 rc0.d
drwxr-xr-x. 2 root root 4.0K Apr 7 18:53 rc1.d
drwxr-xr-x. 2 root root 4.0K Apr 7 18:53 rc2.d
drwxr-xr-x. 2 root root 4.0K Apr 7 18:53 rc3.d
drwxr-xr-x. 2 root root 4.0K Apr 7 18:53 rc4.d
drwxr-xr-x. 2 root root 4.0K Apr 7 18:53 rc5.d
drwxr-xr-x. 2 root root 4.0K Apr 7 18:53 rc6.d
-rwxr-xr-x. 1 root root 340 Dec 29 23:22 rc.local
-rwxr-xr-x. 1 root root 20K Oct 16 2014 rc.sysinit
這里,rc0.d到rc6.d幾個目錄,對應的正是我們之前設置的7個運行級別。聰明的小伙伴看到這里一定猜到了什么了。我們再選rc3.d看看:
[root@www /]# ls -lh /etc/rc.d/rc3.d/
total 0
lrwxrwxrwx. 1 root root 16 Dec 25 06:15 K01smartd -> ../init.d/smartd
lrwxrwxrwx. 1 root root 17 Dec 25 06:10 K02oddjobd -> ../init.d/oddjobd
.
.
.
lrwxrwxrwx. 1 root root 18 Dec 29 22:33 K92iptables -> ../init.d/iptables
lrwxrwxrwx. 1 root root 19 Dec 25 06:31 K95firstboot -> ../init.d/firstboot
lrwxrwxrwx. 1 root root 14 Dec 25 06:15 K99rngd -> ../init.d/rngd
lrwxrwxrwx. 1 root root 17 Dec 25 06:13 S01sysstat -> ../init.d/sysstat
lrwxrwxrwx. 1 root root 22 Dec 25 06:14 S02lvm2-monitor -> ../init.d/lvm2-monitor
lrwxrwxrwx. 1 root root 22 Dec 25 06:36 S03vmware-tools -> ../init.d/vmware-tools
lrwxrwxrwx. 1 root root 17 Dec 25 06:07 S10network -> ../init.d/network
.
.
.
lrwxrwxrwx. 1 root root 15 Apr 7 18:53 S85httpd -> ../init.d/httpd
lrwxrwxrwx. 1 root root 15 Dec 25 06:10 S90crond -> ../init.d/crond
lrwxrwxrwx. 1 root root 13 Dec 25 06:00 S95atd -> ../init.d/atd
lrwxrwxrwx. 1 root root 20 Dec 25 06:10 S99certmonger -> ../init.d/certmonger
lrwxrwxrwx. 1 root root 11 Dec 25 06:07 S99local -> ../rc.local
鑒于編幅,中間省略了一大段,免得被人說我刷稿費呀。
雖然省略了不少內容,但各位有沒有從中發現什么規律呢?
對,里面都是由K01某服務腳本…K99某服務腳本,S01某服務腳本…S99某服務腳本組成。什么意思呢?K##開始的,對應的是關閉某某服務軟件的腳本,而S##對應的,則是開啟某某服務軟件的腳本。比如: K92iptables 的功能,就是關閉iptables服務,而S85httpd,則是開啟httpd服務了。
我們再來看看httpd服務
lrwxrwxrwx. 1 root root 15 Apr 7 18:53 S85httpd -> ../init.d/httpd
S85httpd鏈接到了上級目錄 ../init.d/httpd,因而,實際執行代碼的腳本是在/etc/rc.d/init.d中的httpd腳本。這就是系統存放服務腳本的地方。
每個服務,我們都會按優先級編定不同的次序(S##,K##),然后,在選擇了相應的運行等級里,按次序運行該級別K##的腳本,以實現關閉該級別下的服務,然后,按次序運行該級別S##的腳本,以實現啟動該級別下的服務。
系統腳務腳本與一般腳本的功能一樣,只是在腳本開始的注釋上有所要求,系統服務腳本的格式為:
#!/bin/bash
#
#chkconfig: LLL nn nn
其中,LLL是服務默認啟動的級別,比如LLL為3,4,5,則表示此服務默認在3級別、4級別、5級別下都是運行的。第一個nn則是用于啟動的序號,比如上面的httpd服務,nn是85,則腳本名稱就影射為S85httpd;第二個nn是關閉的序號,又比如上面的iptabled服務,nn為92,則腳本名稱影射為K92iptables。
通過以上的規劃,我們為系統的各種服務設置了各種場景。比如在多用戶模式3級別下,我們可定制系統某些服務在內核啟動后則自動加載運行,某些服務則不加載。在關機模式0級別下,我們可定制系統關閉某服務,然后才安全關機。
最后,系統在執行完上述的腳本命令后,還會默認啟動6個虛擬終端,以等待用戶登錄,提供界面以執行交互式操作。
tty1:2345:respawn:/usr/sbin/mingetty tty1
tty2:2345:respawn:/usr/sbin/mingetty tty2
Tty3:2345:respawn:/usr/sbin/mingetty tty3
tty4:2345:respawn:/usr/sbin/mingetty tty4
Tty5:2345:respawn:/usr/sbin/mingetty tty5
tty6:2345:respawn:/usr/sbin/mingetty tty6
以上,就是CentOS5的系統啟動全過程,是不是覺得眼花瞭亂呢,沒關系,讓我們總結一下整個過程:
CentOS5的系統啟動全過程:
加電自檢(POST)–>Boot Sequence(BIOS) –>BootLoader(MBR)選擇引導的內核–>內核啟動,建立內核空間–>加載根文件系統–>建立用戶空間,并啟動用戶空間的第一個程序 /sbin/init –> (/etc/inittab) –>設置默認運行級別 –> 運行系統初始腳本、完成系統初始化 –> 關閉對應級別下需要關閉的服務,啟動需要啟動的服務 –>設置登錄終端,等待用戶登錄
這樣一整理,是不是覺得整個啟動過程清晰明瞭了 :-)
至于CentOS6,其啟動過程與5其實是大同小異的,只是CentOS6的init配置文件為/etc/init/*.conf下的一堆配置文件,而/etc/inittab 也為兼容5而依然存在。具體到二者的不同,表現在CentOS5的init執行腳本為順序執行,因而在系統啟動時會串行地執行一大堆的腳本命令,效率顯得不高。而CentOS6在其之上稍作改變,init的腳本執行機制類似于并行,因而Upstart的方式比init的方式來得高效。
CentOS6的系統啟動全過程:
加電自檢(POST)–>Boot Sequence(BIOS) –>BootLoader(MBR)選擇引導的內核–>內核啟動,建立內核空間–>加載根文件系統–>建立用戶空間,并啟動用戶空間的第一個程序 /sbin/init –> (/etc/inittab,/etc/init/*.conf) –>設置默認運行級別 –> 運行系統初始腳本、完成系統初始化 –> 關閉對應級別下需要關閉的服務,啟動需要啟動的服務 –>設置登錄終端,等待用戶登錄
上述為CentOS5、CentOS6的系統啟動過程,由于CentOS7采用的是systemd的機制,與上述的兩種機制相比,發生了很大的變化,因而,我會在下篇中詳述。
以上是我對CentOS系統啟動過程的理解!作為初學者,我對linux的認識還是很膚淺,上述可能有不正確的地方,如有錯漏,希望各位能及時指正,共同進步。
我的QQ:153975050
在此感謝馬哥及馬哥團隊,在linux的道路上引領我一直向前!
小斌斌
2016-06-06
原創文章,作者:馬哥Net19_小斌斌,如若轉載,請注明出處:http://www.www58058.com/17856