Linux系統的啓動流程
一、系統啓動流程:
關於Linux系統的啓動流程我們可以按步驟進行劃分爲以下幾個步驟:
POST加電自檢 ==》BIOS(Boot Sequence) ==》 加載對應引導設備上的MBR中的bootloader程序==》主引導設置加載其BootLoader ==》 Kernel初始化==》 initrd==》/etc/init進程加載/etc/inittab.
其進程流程圖如下:
二、剖析詳細啓動流程
(1)、POST開機自檢
電腦主機打開電源的時候,隨後會聽到滴的一聲,系統啓動開始了開機自檢(POST-Power On SelfTest),這個過程中主要是檢測計算機硬件設備比如:CPU,內存,主板,顯卡,CMOS等設備是否有故障存在,如果有硬件故障的話將按兩種情況處理:
對於嚴重故障(致命性故障)則停機,此時由於各種初始化操作還沒完成,不能給出任何提示或信號;
對於非嚴重故障則給出提示或聲音報警信號,等待用戶處理;
如果沒有故障,POST完成自己的接力任務,將尾部工作交接給BIOS處理。
(2)、BIOS
計算機加電自檢完成後第一個讀取的地方就是BIOS(Basic Input Output System,基礎輸入輸出系統),BIOS裏面記錄了主機板的芯片集與相關設置,如CPU與接口設備的通信頻率、啓動設備的搜索順序、硬盤的大小與類型、系統時間、外部總線、各種接口設備的I/O地址、以及與CPU通信的IRQ中斷信息。所以,啓動如果要順利啓動,首先要讀取BIOS設置。但是如果BIOS找不到任何的可引導設備那麼啓動將會失敗。
(3)、安裝BIOS所設定的系統啓動流程
安裝BIOS所設定的系統啓動流程,如果檢測通過,則根據引導次序(Boot Sequence)開始在第一臺設備上支持啓動程序,我們的啓動設備主要包括硬盤、USB、SD等,我們一般用的是硬盤,然後進行讀取的第一個設備就是硬盤,第一個要讀取的就是該硬盤的主引導記錄MBR(Master Boot Record),然後系統可以根據啓動區安裝的引導加載程序(Boot Loader)開始執行核心識別的工作。【MBR一共是512字節,其中前446字節存放的bootloader程序,由它確定選擇的操作系統內核及傳遞給內核的參數和initrd的存放位置。】
(4)、Boot Loader加載Grub程序
在這個過程中主要靠Grub的引導開始的,Grub分爲3個階段:
stage1:主要是Boot Loader,位於MBR中,它的存在是爲了引導stage2;
stage1.5:位於boot分區(基本磁盤分區),爲識別內核文件系統提供文件系統識別擴展。
stage2:也是位於boot分區(基本磁盤分區),Grub的引導程序;
[root@localhost ~]# cd /boot/grub/ [root@localhost grub]# ls abc.xpm.gz fat_stage1_5 iso9660_stage1_5 menu.lstbak splash.xpm.gz ufs2_stage1_5 device.map ffs_stage1_5 jfs_stage1_5 minix_stage1_5 stage1 vstafs_stage1_5 e2fs_stage1_5 grub.conf menu.lst reiserfs_stage1_5 stage2 xfs_stage1_5 [root@localhost grub]#
在/boot/grub/下面我們看到了熟悉的stage1,stage2及grub工具的配置文件grub.conf,那麼grub.conf內都定義了什麼呢?
首先我們先了解一下grub的功能有哪些:
Grub的功能
選擇要啓動的內核或系統;
如果系統有多個內核並存時我們可以通過在系統啓動倒計時我們按任意鍵進入選擇需要用的內核或系統,但是我的系統只有一個操作系統,所以它默認時間一到就進入當前的系統了。
當系統啓動到此時,我們可以輸入e鍵進入交互式界面:
交互式接口
如圖所示,可以按照上面的說明進入交互模式;
基於密碼保護。
在瞭解了grub的功能後我們再來看一下grub.conf的配置文件都配置了些什麼。如下:
# grub.conf generated by anaconda # # Note that you do not have to rerun grubafter making changes to this file # NOTICE: You have a /boot partition. Thismeans that # all kernel and initrd paths are relative to /boot/, eg. # root (hd0,0) # kernel /vmlinuz-version ro root=/dev/mapper/MyGroup-rootfs # initrd /initrd-[generic-]version.img #boot=/dev/sda default=0 #默認選擇的啓動內核(數字對應下方的title編號) timeout=5 #->選擇內核文件超時時間 splashimage=(hd0,0)/grub/splash.xpm.gz #->界面下的系統啓動背景圖片。 hiddenmenu #菜單隱藏。 title CentOS 6 (2.6.32-504.el6.x86_64) #->grub標題 root (hd0,0) #->設定內核文件所在的分區爲grub的根 kernel /vmlinuz-2.6.32-504.el6.x86_64 ro root=/dev/mapper/MyGroup-rootfsrd_LVM_LV=MyGroup/rootfs rd_NO_LUKS.UTF-8 rd_LVM_LV=MyGroup/myswaprd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgbquiet #->定義要使用的內核文件,後面可附加傳遞給內核的啓動參數 initrd /initramfs-2.6.32-504.el6.x86_64.img #->指定爲內核提供額外驅動等功能 #的ra’m disk或ram fs文件
通過該文件我們可以知道了它的配置語法,grub.conf文件的語法如下:
#grub.conf配置文件語法: default=# #→指定默認啓動的內核或OS; timeout=# #→等待用戶選擇要啓動的內核或OS的時長,單位爲秒; splashimage=/path/to/splashimage_file #→指定使用的背景圖片 hiddenmenu #→隱藏菜單 title root (hd0,0)(Device, Part) #→Device表示方式: 在grub中,統統以hd開頭,並緊跟一個數字做各磁盤設備的標記,從0開始編號; Part表示方式:代表分區,從0開始編號 kernel #→指定內核文件及傳遞給內核的參數 參數 #→ro root=/path/to/DEVICE quiet initrd文件 #→通常爲cpio歸檔,並使用gzip壓縮;通常以.img作爲文件名後綴;
(5)、Kernel
根據Grub文件內的定義,grub讀取完畢後就把下面的工作交給內核了。kernel主要是完成系統硬件探測及硬件驅動的初始化,並且以讀寫的方式掛載根文件系統(根切換),那麼這裏就出現了一個那麼這裏就出現了一個"先有雞還是先有蛋的問題了",具體是什麼呢?
要想訪問真正的根文件系統(rootfs)的話,就必須加載根文件系統中的設備,這時根文件系統又沒有掛載,要掛載根文件系統又得加載根文件系統中的驅動程序,那怎麼辦呢?爲了解決這個問題,這是就用到了initrd文件了。
再來說下kernel初始化所要工作的內容做下簡單總結:
探測硬件à加載驅動(initrd)à掛載根文件系統àrootfs (/sbin/init)
這裏要需要做一下說明:initrd和initramfs的區別,首先initrd是系統加載驅動時將內存模擬爲磁盤設備,需要再次在內核中緩存,而initramfs卻將內存直接模擬爲文件系統,這樣它就比起initrd顯得更加的優越。所以在CentOS5上面的initrd在CentOStage6中改成了initramfs。
(6)、到此爲止內核空間的相關工作已經完成,內核空間的任務開始向用戶空間轉移,內核空間通過了一個間接的initrd(微型Linux)向用戶空間的/sbin/init過渡,所以grub開始引導內核轉向initrd。initrd:一個虛擬的文件系統,裏面有lib、bin、sbin、usr、proc、sys、var、dev、boot、等一些目錄,其實你會發現裏面的目錄和實際的文件系統中的目錄樹結構相似,所以我們稱之爲虛擬的根文件系統,作用就是將kernel和真的根文件系統建立關聯關係,讓kernel去initrd中加載根文件系統所需要的驅動程序,並以讀寫的方式掛載根文件系統,並執行用戶空間當中的第一個進程init
[root@192 ~]# mkdir /image #->新建目錄/image [root@192 ~]# cp/boot/initramfs-2.6.32-504.el6.i686.img /image/ #->賦值initramfs至/image目錄下 [root@192 ~]# cd /image/ [root@192 image]# zcatinitramfs-2.6.32-504.el6.i686.img | cpio -id #->將它解壓到當前目錄 80684 blocks [root@192 image]# ls bin mount cmdline netroot dev pre-mount dracut-004-356.el6 pre-pivot emergency pre-trigger etc pre-udev init proc initqueue sbin initqueue-finished sys initqueue-settled sysroot initqueue-timeout tmp initramfs-2.6.32-504.el6.i686.img usr lib var [root@192 image]#看到了initramfs這個映像文件所包含的文件bin,etc,dev,init,dev,lib,sbin,sys,sysroot、proc等,
掛載:將initrd中的proc、sysfs掛載到當前的主分區中的相應目錄;
# mount someimportant things [root@192 image]# mount -t proc proc /proc>/dev/null 2>&1 [root@192 image]# mount -t sysfs sysfs /sys>/dev/null 2>&1
2.通過mknod完成block的創建
[root@192 image]# mknod -m 0666 /dev/null c1 3 [root@192 image]# mknod -m 0666 /dev/ptmx c5 2 [root@192 image]# mknod -m 0600/dev.console c 5 1 [root@192 image]# mknod -m 0660 /dev/kmsg c1 11
3. 創建系統需要的目錄並設定權限:
[root@192 image]# mkdir /dev/shm [root@192 image]# mkdir /dev/pts [root@192 image]# mount -t devpts -ogid=5,mode=620 devpts /dev/pts >/dev/null 2>&1
4. 嘗試掛載根文件系統
5.最後完成根切換
6.init執行完畢以後會啓動系統內的/etc/inittab文件,來完成系統的初始化工作。現在來分析一下inittab這個配置文件內的詳細內容:
上面6行英文註釋主要是告訴我們一些工作室在哪些配置文件裏面去配置的,各個級別的定義:
0:halt #→系統關機狀態 1: single user mode #→單用戶維護狀態 2:multi user mode, without NFS #→多用戶狀態,不支持NFS功能 3: multi user mode, textmode #→完整多用戶模式、字符界面 4:reserved #→系統保留,一般不使用
/etc/inittab文件的格式及語法(CentOS5)
/etc/inittab文件語法格式:
[選項]:[runlevel]:[動作]:[操作]
行爲:
initdefault:設置默認運行級別,無需定義操作
sysinit: 代表系統初始化操作選項;
ctalaltdel:定義組合鍵CtrlAltDel被按下時的動作;
wait:等待系統切換至此級別時運行一次;
respawn:當指定操作進程被關閉時立即再啓動一次;
命令選項:
以下命令,不過通常都是腳本;
下面說下inittab內定義的初始化腳本:/etc/rc.d/rc.sysinit,系統根據運行級別運行相關的服務腳本:/etc/rc.d/init.d/腳本和/etc/rc.d/rc$d
再來看一下rc0-rc6目錄中的文件,以rc3.d爲例:
這些文件都是鏈接文件,它們鏈接到了/etc/init.d/*目錄下的各個程序的,例如ntpd這個腳本:
其實K代表的是該服務下次啓動將會是關閉的,不代表當前這服務就是關閉的,定義的只是下次沖洗系統後是關閉與否;
S代表就是該服務下次啓動將會是隨系統啓動而一起啓動的,但是不代表當前它就是關閉的,定義的只是下次重啓系統後是否開啓;
後面的數字是衆多服務在開機程序中的優先級別,它們的取值是0-99,數字越小,優先級越高;那我們怎麼設置某一服務下次重啓系統後是該關閉或者開啓呢?可以使用chkconfig命令實現:
checkconfig 命令格式: chkconfig [options] Service_Name [on|off] Options: --add #→添加程序服務 --list #→列出當前系統上所有的服務對應的級別是關閉還是啓動 --del #→刪除某個服務(只是刪除鏈接文件,不刪除原文件) --level [on|off] #→指定某個服務對應哪些級別是on或off
例如:
查看至此那個服務的運行信息:0-6級別都是關閉的:
[root@Gmq ~]# chkconfig --list ntpd ntpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
我們將該服務打開:
[root@Gmq ~]# chkconfig ntpd on [root@Gmq ~]# chkconfig --list ntpd ntpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off23452345;chkconfig:
[root@Gmq ~]# vim /etc/init.d/ntpd ....................... ....................... # chkconfig: - 58 74 # description: ntpd is the NTPv4 daemon. \ .......................
我們就看這兩行信息就行啦,其他都是程序自己的一些信息了;
Chkconfig: - 58 74
其中“-”表示的是運行級別,默認就代表2345(難怪上面的那個操作默認就開啓2345級別了)
"58" 代表指定啓動時的優先級;“74”代表指定關閉時的優先級
Description:代表的對這個腳本的一個描述
用戶自定義開機啓動程序,可以根據自己的需求將一些執行命令或是寫到腳本/etc/rc.d/rc.local.當開機時就可以自動加載啦!
三、總結:
Linux系統啓動大概步驟總結如下:
1、 加載BIOS硬件信息,並獲取第一個啓動設備的代號;
2、 讀取第一個啓動設備的mbr到物理內存,物理內存的內容就是Boot Loader了;
3、 運行Boot Loader(如grub,lilo等),初始化硬件設備,建立內存空間映射圖。
4、 根據Boot Loader設定的內核映像路徑,系統讀取內存映像,解壓內核,嘗試驅動所有硬件設備。
5、 運行第一個程序/sbin/init。
6、 執行第一個/etc/rc.d/rc.sysinit腳本程序。
7、 依據/etc/modules.conf裝載內核模塊。
8、 執行不同運行級別的腳本程序
9、 執行/etc/rc.d/rc.local腳本程序;
10、 執行/bin/login,進入等待用戶登錄狀態。
系統初始化的大致內容總結如下:
1、 硬件的初始化,圖像界面啓動的初始化(如果設置了默認啓動腳本)
2、 主機RAID的設置初始化,devicemapper及相關的初始化,
3、 檢測根文件系統,以只讀方式掛載
4、 激活udev和selinux
5、 設置內核參數/etc/sysctl.conf
6、 設置系統時鐘
7、 啓用交換分區,設置主機名
8、 加載鍵盤映射
9、 激活RAID和LVM邏輯卷
10、 掛載額外的文件系統/etc/fstab
等等….
最後根據mingetty程序調用login讓用戶登錄à用戶登錄(系統完成啓動)
在完成啓動過程中主要的腳本和目錄有哪些呢?
boot 目錄
/grub目錄
/boot/grub/grub.conf腳本
/boot/initrd+內核版本 文件
/initrd文件中的init文件
/initrd文件中的/proc/ /sys/ /dev/目錄的掛載及根的切換
/etc/inittab 腳本
/etc/rc.d/rc.sysinit 腳本
還有其他重要的目錄和文件、腳本等,此處不再一一列舉。
不足之處等我學得透徹之後,再來改善!