Linux系統啟動流程
Linux系統從按下開機按鈕到等待用戶輸入用戶名、密碼,這中間到底發生了什麼,本文接下來將要簡單講解一下Linux系統的啟動過程。
Linux系統啟動流程大致是這樣的:
BIOS(Boot Sequence) --> MBR(GRUB,446) --> Kernel --> initrd --> (ROOTFS)/sbin/init(/etc/inittab)
下面詳細講一下其中的每一步。
1. BIOS
BIOS是英文"Basic Input Output System"的縮略詞,直譯過來後中文名稱就是"基本輸入輸出系統"。其實,它是一組固化到計算機內主板上一個ROM芯片上的程序。 主板在接通電源後,BIOS會第一個獲得系統的控制權。BIOS首先會對系統硬件進行檢測(POST, Power On Self Test, 上電自檢),自檢測過程大致為:加電-CPU-ROM-BIOS-System Clock-DMA-64KB RAM-IRQ-顯卡等。如果關鍵部件有問題,計算機會發出報警聲。 自檢一切正常後BIOS會調用一些設備自身ROM中的初始化代碼,對這些設備進行初始化,比如顯卡。這時可以看到一些初始化信息,介紹生產廠商、芯片類型等內容。 最後,BIOS會根據COMS中設置的啟動順序(Boot Sequence),依次嘗試啟動。當啟動設備是硬盤時,BIOS會把系統控制權交給硬盤MBR中的bootloader。 http://baike.baidu.com/link?url=3u5SmrzMeDuUNAo9rqDc4Vxo8mN0n-7OCLMurOs4yxGXL1ffjnIh0BAsyFm5Elai4ijwxk8dQEVKEHhqWtbHoa
2. MBR
MBR是Master Boot Record的簡寫, 即主引導記錄。MBR記錄一般在磁盤 0 磁道 1 扇區,共512個字節。前446個字節是BootLoader(引導程序),後 4*16 的 64 個字節是存放分區信息的,最後 2 個字節是校驗信息,一般是 55AA。 大多數Linux系統使用GRUB作為BootLoader。GRUB可以引導多種操作系統,它可以識別磁盤文件系統的格式,所以只需要內核文件名和內核所在分區就可以加載內核,通過/boot/grub/grub.conf文體來配置這些信息。 GRUB是模塊化的,運行時經歷如下階段:
Stage 1 Stage1 的代碼保存在MBR中前446字節。 將MBR導出為文件後查看 # dd if=/dev/sda count=1 of=/tmp/MBR 1+0 records in 1+0 records out 512 bytes (512 B) copied, 0.000283544 s, 1.8 MB/s # file /tmp/MBR /tmp/MBR: x86 boot sector; GRand Unified Bootloader, stage1 version 0x3, boot drive 0x80, 1st sector stage2 0x8480e, GRUB version 0.94; partition 1: ID=0x83, active, starthead 32, startsector 2048, 1024000 sectors; partition 2: ID=0x8e, starthead 221, startsector 1026048, 82860032 sectors, code offset 0x48
/boot/grub/stage1 是stage 1未作修改的代碼備份。 # file /boot/grub/stage1 /boot/grub/stage1: x86 boot sector; GRand Unified Bootloader, stage1 version 0x3, GRUB version 0.94, code offset 0x48
Stage 1_5 Stage1_5的代碼允許GRUB識別多種類型的文件系統,識別每個文件系統的代碼的代碼保存在/boot/grub/*stage1_5 的文件中。 # cd /boot/grub # ls *stage1_5 e2fs_stage1_5 iso9660_stage1_5 reiserfs_stage1_5 xfs_stage1_5 fat_stage1_5 jfs_stage1_5 ufs2_stage1_5 ffs_stage1_5 minix_stage1_5 vstafs_stage1_5
Stage 2 Stage 2 代碼讀取/boot/grub/grub.conf文件,決定如何加載內核,Stage2的代碼保存在文件/boot/grub/stage2中: # ls -al /boot/grub/stage2 -rw-r--r--. 1 root root 125976 Jun 28 2012 /boot/grub/stage2
3. Kernel
GRUB的最後階段stage2會根據/boot/grub/grub.conf文件中的配置加載kernel到內存中,並將系統控制權交給kernel。
4. initrd
initrd是"initial RAM disk"的縮寫,隨kernel一起被GRUB加載進內存,在系統引導過程中掛載的一個臨時根文件系統。 Linux內核在設計風格上屬於單內核,文件系統、進程管理、內存管理都需要內核來完成,這樣勢必會造成內核代碼非常龐大。為了減少linux內核的大小,Linux系統內核被分成了內核和內核模塊,內核會根據平台需要動態加載內核模塊,非核心功能通常做成內核模塊,比如大多數設備驅動。 這樣勢必會產生矛盾,比如,如果Linux內核中沒有集成識別ext3文件系統的模塊,而ext3模塊卻在ext3文件系統中。這時,Linux內核訪問文件系統需要拿到這個模塊,而這個模塊又在文件系統中。這樣就能看出使用initrd的必要了。 在linux 2.5內核開始引入initramfs技術,作用與initrd類似,都是 由內核執行其上的某個程序(initrd是/linuxrc, initramfs是/init)。區別是 /linuxrc不是以PID=1執行的, 因為 1這個進程ID是給/sbin/init保留的。initrd機制找到真正的根設備後將其設備號寫入/proc/sys/kernel/real-root-dev, 然後控制轉移到內核由 其裝載根文件系統並啟動/sbin/init。initramfs機制中/init以PID=1執行,由init裝載根文件 系統並用exec轉到真正的/sbin/init, 這樣簡化了啟動流程,減少了啟動時間。
5.init
/sbin/init進程是Linux啟動的第一個進程,PID=1。Linux 系統的 init 進程經歷了兩次重大的演進,傳統的 sysvinit 已經淡出歷史舞台,新系統 UpStart 和 systemd 各有特點。 sysvinit讀取的一個主配置文件是/etc/inittab,文件格式參考這裡主要定義的設置有: 1. 定義默認啟動級別 2. 系統初始化階段調用rc.sysinit 3. 調用rc腳本,傳入運行級別作為參數,啟動和關閉對應級別的服務 4. ctrl+alt+del組合按鍵的動作 5. 6個虛擬終端 7. 運行級別為5時啟動窗口顯示管理器 而UpStart則僅保留sysvinit的inittab文件中默認啟動級別,其它的配置分散到了/etc/init/*.conf多個文件中。
<span style="font-size:14px;">[rising@centos ~]$ ls /etc/init
control-alt-delete.conf prefdm.conf rcS-emergency.conf readahead-disable-services.conf tty.conf
init-system-dbus.conf quit-plymouth.conf rcS-sulogin.conf serial.conf
kexec-disable.conf rc.conf readahead-collector.conf splash-manager.conf
plymouth-shutdown.conf rcS.conf readahead.conf start-ttys.conf</span>
init程序(sysvinit)讀取或運行的文件順序如下: init -> inittab -> rc.sysinit -> rc -> rc.local -> mingetty tty[1-6] -> X11/prefdm
/etc/inittab的任務:
1、設定默認運行級別;
2、運行系統初始化腳本;
3、運行指定運行級別對應的目錄下的腳本;
4、設定Ctrl+Alt+Del組合鍵的操作;
5、定義UPS電源在電源故障/恢復時執行的操作;
6、啟動虛擬終端(2345級別);
7、啟動圖形終端(5級別);
/etc/rc.d/rc.sysinit完成的任務:
1、激活udev和selinux;
2、根據/etc/sysctl.conf文件,來設定內核參數;
3、設定時鐘時鐘;
4、裝載鍵盤映射;
5、啟用交換分區;
6、設置主機名;
7、根文件系統檢測,並以讀寫方式重新掛載;
8、激活RAID和LVM設備;
9、啟用磁盤配額;
10、根據/etc/fstab,檢查並掛載其它文件系統;
11、清理過期的鎖和PID文件;
/etc/rc.d/rc文件中