前言:
作爲一個Linux用戶,每天都在Linux系統中進行各種各樣的操作,或工作、或學習、或娛樂,那麼Linux系統的啓動流程是怎樣的呢?
本文將就Linux系統的啓動做一個詳細的說明,也爲以後的系統裁剪工作打下堅實的基礎。
開始:
先上圖
上圖就是Linux系統的一個啓動流程圖,接下來會對各個啓動流程進行說明。
第一回合:開機自檢(BIOS)
計算機在接通電源之後首先會由BIOS進行POST自檢,然後根據BIOS內設置的引導順序從硬盤、軟盤或者CDROM中讀入“引導塊”。在 PC 中,引導 Linux 是從 BIOS 中的地址 0xFFFF0 處開始的。BIOS 的第一個步驟是加電自檢(POST)。POST 的工作是對硬件進行檢測。BIOS 的第二個步驟是進行本地設備的枚舉和初始化。給定 BIOS 功能的不同用法之後,BIOS 由兩部分組成:POST 代碼和運行時服務。當 POST 完成之後,它被從內存中清理了出來,但是 BIOS 運行時服務依然保留在內存中,目標操作系統可以使用這些服務。
第二回合:MBR引導
自檢通過後,我們的系統通常會從硬盤引導的,其中主引導分區,也就是我們的MBR中包含主引導加載程序。MBR位於磁盤的第一個扇區中(0磁道0柱面1扇區),大小爲521字節,其中前446字節爲引導程序,中間64字節爲分區表,最後2個字節爲硬盤有效標誌。
第三回合:GRUB引導
前面我們說過,MBR中包含主引導加載程序,也就是Boot Loader,在Linux系統中,有GRUB和LILO兩種引導加載程序,由於LILO沒有交互式命令界面,也不支持網絡引導,所以現在已經逐漸的被淘汰,取而代之的就是功能強大的GRUB引導加載程序。
GRUB分爲三個階段
第一階段:stage 1:也就是Boot Loader,位於MBR中,作用爲引導stage2
第二階段:stage1.5:位於boot分區,作用:識別內核文件系提供的文件系統、識別擴展
第三階段:stage2:也位於boot分區,作用:Grub的引導程序
在/boot/grub目錄下看以看到這些stage
[root@myb362 grub]# ls /boot/grub/ device.map grub.conf minix_stage1_5 stage2 e2fs_stage1_5 iso9660_stage1_5 reiserfs_stage1_5 ufs2_stage1_5 fat_stage1_5 jfs_stage1_5 splash.xpm.gz vstafs_stage1_5 ffs_stage1_5 menu.lst stage1 xfs_stage1_5
GRUB引導加載程序是由一個配置文件控制的,如果這個配置文件中沒有任何信息或者配置錯誤的話,開機之後就會自動轉到GRUB命令行界面。
grub.conf文件
# grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE: You have a /boot partition. This means that # all kernel and initrd paths are relative to /boot/, eg. # root (hd0,0) # kernel /vmlinuz-version ro root=/dev/mapper/vg_myb362-lv_root # initrd /initrd-[generic-]version.img #boot=/dev/sda default=0 #0表示默認啓動第一個title timeout=5 #默認5秒自動進入操作系統 splashimage=(hd0,0)/grub/splash.xpm.gz#設置GRUB背景圖片 hiddenmenu#表示隱藏GRUB的啓動菜單,可選項 title CentOS (2.6.32-358.el6.x86_64)#定義一個操作系統以及名字 root (hd0,0)#指定相應的Linux所有的/boot分區(hd0,0)表示第一塊硬盤的第一個分區 kernel /vmlinuz-2.6.32-358.el6.x86_64 ro root=/dev/mapper/vg_myb362-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_NO_DM rd_LVM_LV=vg_myb362/lv_swap KEYBOARDTYPE=pc KEYTABLE=us rd_LVM_LV=vg_myb362/lv_root rhgb quiet #這麼一長串指定的是kernel的絕對路徑和一些啓動選項 initrd /initramfs-2.6.32-358.el6.x86_64.img#指定initrd文件的路徑
第四回合:加載內核kernel
加載內核kernel實際上將內核映像加載到內存中,內核映像通常是一個zImage(壓縮映像,小於512KB)或者一個bzImage(比較大的壓縮映像,大於512KB),是之前就通過zlib進行壓縮過的。其實在內核映像之前還有一個例程,它實現了少量硬件設置,並對內核映像中所包含的內核進行解壓,然後將其放入高端內存中。然後kernel就要以讀寫的方式掛載根文件系統(chroot切換),那就有一個問題了,要想掛載根文件系統rootfs,那麼就需要裝載根文件系統模塊,然而這個模塊在/lib/modules/`uname -r`下,那麼問題就出現了,根沒有掛載上,我怎麼能找到這個模塊呢?這就需要用到initrd了,initrd是安裝在內存中一個臨時的根,從這個臨時根中我們就可以獲取並裝載這個模塊,接着使用chroot切換到我們的真實根下,就實現了根文件系統的掛載。那麼簡單總結一下kernel的工作流程就是
探測硬件-->加載驅動(initrd)-->掛載根文件系統-->rootfs(/sbin/init)
註釋:initrd是RHEL5上的,在RHEL6上是initramfs,initrd的工作流程是系統加載驅動時將內存模擬成磁盤設備,需要再次在內存中緩存,而initramfs則是直接將內存模擬成文件系統,直接使用內存的速度肯定要比使用硬盤的速度快的多,所以在最新的RHEL6上是使用了initramfs。
initrd和initramfs文件都是可以在/boot目錄下找到的,文件名爲
RHEL5:/boot/initrd-`uname -r`.img
RHEL6:/boot/initramfs-`uname -r`.img
我們展開一下RHEL6下的initramfs來看一下
[root@myb362 initramfs]# mkdir ~/initramfs #創建一個目錄用來存放文件 [root@myb362 initramfs]# cp /boot/initramfs-2.6.32-431.11.2.el6.x86_64.img ~/initramfs/ #複製到該目錄 [root@myb362 initramfs]# cd ~/initramfs/#切換到該目錄 [root@myb362 initramfs]# zcat initramfs-2.6.32-431.11.2.el6.x86_64.img | cpio -id#展開initramfs文件 91602 blocks [root@myb362 initramfs]# ls#使用ls查看裏面的文件 bin initqueue-settled proc cmdline initqueue-timeout sbin dev initramfs-2.6.32-431.11.2.el6.x86_64.img sys dracut-004-336.el6_5.2 lib sysroot emergency lib64 tmp etc mount usr init pre-pivot var initqueue pre-trigger initqueue-finished pre-udev
可以看到很多熟悉的目錄bin、lib、sbin、lib64、sys、sysroot、proc......這就是initramfs\initrd可以爲我們裝載模塊並且切換根的原因。
當然,這裏還有一個init腳本文件,這個init腳本文件中與/sbin/init可不是相同的。打開來看之後,你會發現他就是進行了一些操作之後切換到真實根,具體在切換根之前做了哪些操作,可以打開這個腳本簡單看一下。
接下來就可以交給init來工作了。
第五回合:啓動init
init進程是系統所有進程的起點,內核在完成核內引導之後,即在本線程(進程)空間內加載init程序,init的進程號是1.init進程是所有進程的發起者和控制者。因爲在任何基於Unix的系統(比如Linux)中,它都是第一個運行的進程,所有init進程的編號(Porcess ID ,PID)永遠是1,。如果init出現了問題,那麼系統的其餘部分也就隨之而垮掉了。
init進程有兩個作用。第一個作用是扮演終結父進程的角色。因爲init進程永遠不會被終止,所以系統總是可以確信它的存在,並在必要的時候以它爲參照。如果某個進程在它衍生出來的全部子進程結束之前被終止,就會出現必須以init爲參照物的情況。此時那些失去了父進程的子進程的子進程就都會以init作爲他們的父進程。
init的第二個作用是在進入某個特定的運行級別(Runlevel)時運行相應的程序,以此對各種運行級別進行管理。它的這個作用是由/etc/inittab文件定義的。也就是下邊會講到的。
第六回合:通過/etc/inittab文件進行初始化
init的工作是根據/etc/inittab來執行相應的腳本進行系統初始化,比如設置鍵盤、字體、裝載模塊、設置網絡等等。
說明:在RHEL5中,是根據/etc/inittab來執行相應的腳本,但是在RHEL6中,是根據/etc/init/*.conf文件來執行相應的腳本的。
爲了更好的演示,那我們來看一下RHEL5中的/etc/inittab文件
# inittab This file describes how the INIT process should set up # the system in a certain run-level. # # Author: Miquel van Smoorenburg, <[email protected]> # Modified for RHS Linux by Marc Ewing and Donnie Barnes # # Default runlevel. The runlevels used by RHS 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: # System initialization. si::sysinit:/etc/rc.d/rc.sysinit 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 # Things to run in every runlevel ud::once:/sbin/update # Trap CTRL-ALT-DELETE ca::ctrlaltdel:/sbin/shutdown -t3 -r now # When our UPS tells us power has failed, assume we have a few minutes # of power left. Schedule a shutdown for 2 minutes from now. # This does, of course, assume you have powerd installed and your # UPS connected and working correctly. pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down" # If power was restored before the shutdown kicked in, cancel it. pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled" # If power was restored before the shutdown kicked in, cancel it. pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled" # Run gettys in standard runlevels 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 # Run xdm in runlevel 5 x:5:respawn:/etc/X11/prefdm -nodaemon
配置文件很長,我們拆開來說:
系統運行級別
#這是運行級別,一共7個級別,0-6 # Default runlevel. The runlevels used by RHS 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)#多用戶模式,無NFS功能 # 3 - Full multiuser mode#字符界面 # 4 - unused#未使用 # 5 - X11#圖形界面 # 6 - reboot (Do NOT set initdefault to this)#重啓 #
系統默認運行級別
id:3:initdefault:
初始化系統腳本,後邊會繼續講
si::sysinit:/etc/rc.d/rc.sysinit
定義不同級別下啓動的服務
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
定義ALT+CTRL+DEL組合鍵的動作,很熟悉有沒有。
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
定義電源選項:
# UPS connected and working correctly. pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down" # If power was restored before the shutdown kicked in, cancel it. pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled" # If power was restored before the shutdown kicked in, cancel it. pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
定義虛擬終端個數:
# Run gettys in standard runlevels 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
好了,這就是分割之後這些腳本的功能,那麼你可能也發現了這個腳本的語法格式是
[選項]:[runlevel]:[動作]:[操作]
這裏其他的沒什麼好說了,就先來說說這些動作的含義
initdefault:設置默認運行級別,無需定義操作
sysinit:代表系統初始化操作選項
ctrlaltdel:定義組合鍵Ctrl+Alt+Del被按下時的動作
wait:等待系統切換到此級別時運行一次
respawn:當指定操作進程被關閉時立即再啓動一次
好了,還記得剛纔看到的/etc/inittab文件中的初始化腳本那一行嗎?接下來就來說說rc.sysinit。
第七回合:執行/etc/rc.d/rc.sysinit初始化腳本
這個初始化腳本主要完成這些任務:
激活selinux和udev
根據/etc/sysctl.conf文件設置內核參數
設置系統時鐘
裝載鍵映射
啓用交換分區
設置主機名
根文件系統檢測並重新掛載其爲讀寫;
激活RAID和LVM;
檢查和掛載其它文件系統;/etc/fstab中定義;
裝入模塊/etc/rc.d/rcX.d/[K/S]
清理操作;
由於這個腳本實在太大,這裏不便貼出,就只列出這個腳本執行的任務。
初始化腳本時會根據當前運行級別
裝入不同的模塊,模塊在/etc/rc.d/rcX.d/目錄下,如果是運行3級別,則裝載/etc/rc.d/rcX.d/目錄下的[K/S]模塊
我們隨便打開/etc/rc.d/rc3.d目錄看下
可以看到,這裏的都是鏈接文件,而鏈接的這些文件則都是一些程序腳本。
那開頭S25*或者K89*又是什麼意思呢?
S:表示系統在此級別下運行時,啓動的服務
K:表示系統在此級別下運行時,關閉的服務
數字:表示服務的優先級,取值範圍是0-99,數字越小,優先級越高。
而且,這些文件的命名方式都是由這些程序腳本決定的。我們隨便打開一個rsyslog的服務腳本看一下
[root@myb362 init]# cat /etc/init.d/rsyslog #!/bin/bash # # rsyslog Startup script for rsyslog.#服務腳本介紹 # # chkconfig: 2345 12 88#不同級別下的啓動與否 # description: Syslog is the facility by which many daemons use to log \#腳本描述
就看這一行好了
# chkconfig: 2345 12 88
2345:表示運行級別:2、3、4、5
12:表示啓動優先級
88:表示關閉優先級
那麼這一行就意味着:在2、3、4、5級別下,rsyslog會啓動,並且優先級爲12,在0,1,6級別下關閉,並且優先級爲88
我們可以在這改配置文件來決定程序在不同級別下是否啓動和優先級,也可以通過命令來改變程序的啓動與否
checkconfig 命令格式: chkconfig [options] Service_Name [on|off] Options:--add #添加程序 --list #列出當前系統上有的程序在不同級別下的啓動與否 --del #刪除某個服務(只是刪除鏈接文件,不刪除原文件) --level [on|off] #設置程序在某級別下的啓動與否(on或off)
列出rsyslog程序的啓動級別
[root@myb362 init]# chkconfig --list rsyslog rsyslog 0:off 1:off 2:on 3:on 4:on 5:on 6:off
改變rsyslog程序的啓動級別
[root@myb362 init]# chkconfig --level 24 rsyslog off [root@myb362 init]# chkconfig --list rsyslog rsyslog 0:off 1:off 2:off 3:on 4:off 5:on 6:off
第八回合:執行/sbin/mingetty,啓動Login Shell,這個就不說了,就是系統成功啓動後出來的那個提示框。
總結:Linux系統啓動流程大概就是這樣,經過這樣一寫,對系統又有了一些比較深的理解。每天進步一點,總有成功那天。明天就要做系統裁剪了,歡迎大家關注!