Linux操作系統啟動過程詳解
如果你對Linux操作系統有一定的了解,想對其更深層次的東西做進一步探究。這當中就包括系統的啟動流程、文件系統的組成結構、基于動態庫和靜態庫的程序在執行時的異同、協議棧的架構和原理、驅動程序的機制等等。
其中Linux操作系統啟動過程肯定是大家最有興趣了解的,這里在綜合了現有網上大家智慧的基礎上,基于2.6.32的內核的CentOS 6.0系統,對Linux的啟動流程做了些分析,希望對大家有所幫助。
OK,我們言歸正傳。對于一臺安裝了Linux系統的主機來說,當用戶按下開機按鈕時,一共要經歷以下幾個過程,如圖:
其中,每個過程都執行了自己該做的初始化部分的事情,有些過程又可分為好幾個子過程。接下來,我們就對每個階段做一個詳細分析和講解。
一、BIOS自檢
稍有計算機基礎的人都應該聽過BIOS(Basic Input / Output System),又稱基本輸入輸出系統,可以視為是一個永久地記錄在ROM中的一個軟件,是操作系統輸入輸出管理系統的一部分。早期的BIOS芯片確實是”只讀”的,里面的內容是用一種燒錄器寫入的,一旦寫入就不能更改,除非更換芯片。現在的主機板都使用一種叫Flash EPROM的芯片來存儲系統BIOS,里面的內容可通過使用主板廠商提供的擦寫程序擦除后重新寫入,這樣就給用戶升級BIOS提供了極大的方便。
BIOS的功能由兩部分組成,分別是POST碼和Runtime服務。POST階段完成后它將從存儲器中被清除,而Runtime服務會被一直保留,用于目標操作系統的啟動。BIOS兩個階段所做的詳細工作如下:
步驟1:上電自檢POST(Power-on self test),主要負責檢測系統外圍關鍵設備(如:CPU、內存、顯卡、I/O、鍵盤鼠標等)是否正常。例如,最常見的是內存松動的情況,BIOS自檢階段會報錯,系統就無法啟動起來;
步驟2:步驟1成功后,便會執行一段小程序用來枚舉本地設備并對其初始化。這一步主要是根據我們在BIOS中設置的系統啟動順序來搜索用于啟動系統的驅動器,如硬盤、光盤、U盤、軟盤和網絡等。我們以硬盤啟動為例,BIOS此時去讀取硬盤驅動器的第一個扇區(MBR,512字節),然后執行里面的代碼。實際上這里BIOS并不關心啟動設備第一個扇區中是什么內容,它只是負責讀取該扇區內容、并執行。
至此,BIOS的任務就完成了,此后將系統啟動的控制權移交到MBR部分的代碼。
PS:在個人電腦中,Linux的啟動是從0xFFFF0地址開始的。
如果你對Linux操作系統有一定的了解,想對其更深層次的東西做進一步探究。這當中就包括系統的啟動流程、文件系統的組成結構、基于動態庫和靜態庫的程序在執行時的異同、協議棧的架構和原理、驅動程序的機制等等。
其中Linux操作系統啟動過程肯定是大家最有興趣了解的,這里在綜合了現有網上大家智慧的基礎上,基于2.6.32的內核的CentOS 6.0系統,對Linux的啟動流程做了些分析,希望對大家有所幫助。
OK,我們言歸正傳。對于一臺安裝了Linux系統的主機來說,當用戶按下開機按鈕時,一共要經歷以下幾個過程,如圖:
其中,每個過程都執行了自己該做的初始化部分的事情,有些過程又可分為好幾個子過程。接下來,我們就對每個階段做一個詳細分析和講解。
一、BIOS自檢
稍有計算機基礎的人都應該聽過BIOS(Basic Input / Output System),又稱基本輸入輸出系統,可以視為是一個永久地記錄在ROM中的一個軟件,是操作系統輸入輸出管理系統的一部分。早期的BIOS芯片確實是”只讀”的,里面的內容是用一種燒錄器寫入的,一旦寫入就不能更改,除非更換芯片?,F在的主機板都使用一種叫Flash EPROM的芯片來存儲系統BIOS,里面的內容可通過使用主板廠商提供的擦寫程序擦除后重新寫入,這樣就給用戶升級BIOS提供了極大的方便。
BIOS的功能由兩部分組成,分別是POST碼和Runtime服務。POST階段完成后它將從存儲器中被清除,而Runtime服務會被一直保留,用于目標操作系統的啟動。BIOS兩個階段所做的詳細工作如下:
步驟1:上電自檢POST(Power-on self test),主要負責檢測系統外圍關鍵設備(如:CPU、內存、顯卡、I/O、鍵盤鼠標等)是否正常。例如,最常見的是內存松動的情況,BIOS自檢階段會報錯,系統就無法啟動起來;
步驟2:步驟1成功后,便會執行一段小程序用來枚舉本地設備并對其初始化。這一步主要是根據我們在BIOS中設置的系統啟動順序來搜索用于啟動系統的驅動器,如硬盤、光盤、U盤、軟盤和網絡等。我們以硬盤啟動為例,BIOS此時去讀取硬盤驅動器的第一個扇區(MBR,512字節),然后執行里面的代碼。實際上這里BIOS并不關心啟動設備第一個扇區中是什么內容,它只是負責讀取該扇區內容、并執行。
至此,BIOS的任務就完成了,此后將系統啟動的控制權移交到MBR部分的代碼。
PS:在個人電腦中,Linux的啟動是從0xFFFF0地址開始的。
另外一個概念:initramfs
initramfs 是在 kernel 2.5中引入的技術,實際上它的含義就是:在內核鏡像中附加一個cpio包,這個cpio包中包含了一個小型的文件系統,當內核啟動時,內核將這個 cpio包解開,并且將其中包含的文件系統釋放到rootfs中,內核中的一部分初始化代碼會放到這個文件系統中,作為用戶層進程來執行。這樣帶來的明顯的好處是精簡了內核的初始化代碼,而且使得內核的初始化過程更容易定制。
疑惑的是:我的內核是2.6.32-71.el6.i686版本,但在我的/boot分區下面卻存在的是/boot/initramfs-2.6.32-71.el6.i686.img類型的文件,沒搞明白,還望高人解惑。我只知道在2.6內核中支持兩種格式的initrd,一種是2.4內核的文件系統鏡像image-initrd,一種是cpio格式。接下來我們就來探究一下initramfs-2.6.32-71.el6.i686.img里到底放了那些東西。
在tmp文件夾中解壓initrd.img里的內容:
如果initrd.img文件的格式顯示為“initrd.img:ISO 9660 CD-ROM filesystem data”,則可直接輸入命令“mount -o loop initrd.img /mnt/test”進行掛載。
通過上的分析和我們的驗證,我們確實得到了這樣的結論:
grub的stage2將initrd加載到內存里,讓后將其中的內容釋放到內容中,內核便去執行initrd中的init腳本,這時內核將控制權交給了init文件處理。我們簡單瀏覽一下init腳本的內容,發現它也主要是加載各種存儲介質相關的設備驅動程序。當所需的驅動程序加載完后,會創建一個根設備,然后將根文件系統rootfs以只讀的方式掛載。這一步結束后,釋放未使用的內存,轉換到真正的根文件系統上面去,同時運行/sbin/init程序,執行系統的1號進程。此后系統的控制權就全權交給/sbin/init進程了。
四、初始化系統
經過千辛萬苦的跋涉,我們終于接近黎明的曙光了。接下來就是最后一步了:初始化系統。/sbin/init進程是系統其他所有進程的父進程,當它接管了系統的控制權先之后,它首先會去讀取/etc/inittab文件來執行相應的腳本進行系統初始化,如設置鍵盤、字體,裝載模塊,設置網絡等。主要包括以下工作:
1. 執行系統初始化腳本(/etc/rc.d/rc.sysinit),對系統進行基本的配置,以讀寫方式掛載根文件系統及其它文件系統,到此系統算是基本運行起來了,后面需要進行運行級別的確定及相應服務的啟動。rc.sysinit所做的事情(不同的Linux發行版,該文件可能有些差異)如下:
(1)獲取網絡環境與主機類型。首先會讀取網絡環境設置文件”/etc/sysconfig/network”,獲取主機名稱與默認網關等網絡環境。
?。?)測試與載入內存設備/proc及usb設備/sys。除了/proc外,系統會主動檢測是否有usb設備,并主動加載usb驅動,嘗試載入usb文件系統。
?。?)決定是否啟動SELinux。
?。?)接口設備的檢測與即插即用(pnp)參數的測試。
(5)用戶自定義模塊的加載。用戶可以再”/etc/sysconfig/modules/*.modules”加入自定義的模塊,此時會加載到系統中。
(6)加載核心的相關設置。按”/etc/sysctl.conf”這個文件的設置值配置功能。
?。?)設置系統時間(clock)。
?。?)設置終端的控制臺的字形。
?。?)設置raid及LVM等硬盤功能。
?。?0)以方式查看檢驗磁盤文件系統。
?。?1)進行磁盤配額quota的轉換。
?。?2)重新以讀取模式載入系統磁盤。
?。?3)啟動quota功能。
(14)啟動系統隨機數設備(產生隨機數功能)。
(15)清楚啟動過程中的臨時文件。
(16)將啟動信息加載到”/var/log/dmesg”文件中。
當/etc/rc.d/rc.sysinit執行完后,系統就可以順利工作了,只是還需要啟動系統所需要的各種服務,這樣主機才可以提供相關的網絡和主機功能,因此便會執行下面的腳本。
2. 執行/etc/rc.d/rc腳本。該文件定義了服務啟動的順序是先K后S,而具體的每個運行級別的服務狀態是放在/etc/rc.d/rc*.d(*=0~6)目錄下,所有的文件均是指向/etc/init.d下相應文件的符號鏈接。rc.sysinit通過分析/etc/inittab文件來確定系統的啟動級別,然后才去執行/etc/rc.d/rc*.d下的文件。
/etc/init.d-> /etc/rc.d/init.d
/etc/rc ->/etc/rc.d/rc
/etc/rc*.d ->/etc/rc.d/rc*.d
/etc/rc.local-> /etc/rc.d/rc.local
/etc/rc.sysinit-> /etc/rc.d/rc.sysinit
也就是說,/etc目錄下的init.d、rc、rc*.d、rc.local和rc.sysinit均是指向/etc/rc.d目錄下相應文件和文件夾的符號鏈接。我們以啟動級別3為例來簡要說明一下。
/etc/rc.d/rc3.d目錄,該目錄下的內容全部都是以 S 或 K 開頭的鏈接文件,都鏈接到”/etc/rc.d/init.d”目錄下的各種shell腳本。S表示的是啟動時需要start的服務內容,K表示關機時需要關閉的服務內容。/etc/rc.d/rc*.d中的系統服務會在系統后臺啟動,如果要對某個運行級別中的服務進行更具體的定制,通過chkconfig命令來操作,或者通過setup、ntsys、system-config-services來進行定制。如果我們需要自己增加啟動的內容,可以在init.d目錄中增加相關的shell腳本,然后在rc*.d目錄中建立鏈接文件指向該shell腳本。這些shell腳本的啟動或結束順序是由S或K字母后面的數字決定,數字越小的腳本越先執行。例如,/etc/rc.d/rc3.d /S01sysstat就比/etc/rc.d/rc3.d /S99local先執行。 3. 執行用戶自定義引導程序/etc/rc.d/rc.local。其實當執行/etc/rc.d/rc3.d/S99local時,它就是在執行/etc/rc.d/rc.local。S99local是指向rc.local的符號鏈接。就是一般來說,自定義的程序不需要執行上面所說的繁瑣的建立shell增加鏈接文件的步驟,只需要將命令放在rc.local里面就可以了,這個shell腳本就是保留給用戶自定義啟動內容的。
4. 完成了系統所有的啟動任務后,linux會啟動終端或X-Window來等待用戶登錄。tty1,tty2,tty3…這表示在運行等級1,2,3,4的時候,都會執行”/sbin/mingetty”,而且執行了6個,所以linux會有6個純文本終端,mingetty就是啟動終端的命令。
除了這6個之外還會執行”/etc/X11/prefdm-nodaemon”這個主要啟動X-Window
至此,系統就啟動完畢了。
PS: 最后附上一張非常完整的系統啟動流程圖,適合各個水平階段的讀者。
posted on 2013-12-27 11:02 順其自然EVO 閱讀(294) 評論(0) 編輯 收藏 所屬分類: linux