Linux系統啓動流程

Linux系統啓動流程

Linux系統從按下開機按鈕到等待用戶輸入用戶名、密碼,這中間到底發生了什麼,本文接下來將要簡單講解一下Linux系統的啓動過程。

Linux系統啓動流程大致是這樣的:

BIOS(Boot Sequence) --> MBR(GRUB) --> 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。

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,文件格式參考這裏
inittab文件主要完成的配置有:
    1. 定義默認啓動級別
    2. 系統初始化階段調用rc.sysinit
    3. 調用rc腳本,傳入運行級別作爲參數,啓動和關閉對應級別的服務
    4. ctrl+alt+del組合按鍵的動作
    5. 6個虛擬終端
    7. 運行級別爲5時啓動窗口顯示管理器

而UpStart則僅保留sysvinit的inittab文件中默認啓動級別,其它的配置分散到了/etc/init/*.conf多個文件中。

[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

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文件中
有如下的shell代碼,負責運行指定運行級別對應的目錄下的腳本,接受一個參數作爲運行級別
for I in /etc/rc$1.d/K*; do
  $I stop
done
 
for I in /etc/rc$1.d/S*; do
  $I start
done
 
關閉或啓動的優先次序,數據越小越優先被選定
先關閉以K開頭的服務,後啓動以S開頭的服務;

/etc/rc.d/rc.local:
系統最後執行的一個腳本。一般被鏈接爲S99local,被/etc/rc.d/rc腳步執行。

mingetty 
inittab文件中定義了多個虛擬終端運行的程序。mingetty會啓動login程序進行身份驗證。




發佈了30 篇原創文章 · 獲贊 55 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章