[RedHat] (原創)Linux 操作系統啓動流程以及trouble shooting思路

Linux系統啓動的基本過程和步驟:

最近在某個版塊看到有人討論GRUB的問題,這裏是我個人的一些理解。
我想大部分還是正確的,但肯定也有理解錯誤的地方,在這裏拋磚引玉了!

Linux系統啓動過程大致按照如下步驟進行(這是一個簡述):
第一階段:BIOS啓動引導階段;
                        在該過程中實現硬件的初始化以及查找啓動介質;
                        從MBR中裝載啓動引導管理器(GRUB)並運行該啓動引導管理
第二階段:GRUB啓動引導階段;
                        裝載stage1
                        裝載stage1.5
                        裝載stage2
                        讀取/boot/grub.conf文件並顯示啓動菜單;
                        裝載所選的kernel和initrd文件到內存中
第三階段:內核階段:
                        運行內核啓動參數;
                        解壓initrd文件並掛載initd文件系統,裝載必須的驅動;
                        掛載根文件系統
第四階段:Sys V init初始化階段:
                        啓動/sbin/init程序;
                        運行rc.sysinit腳本,設置系統環境,啓動swap分區,檢查和掛載文件系統;
                        讀取/etc/inittab文件,運行在/et/rc.d/rc<#>.d中定義的不同運行級別的服務初始化腳本;
                        打開字符終端1-6號控制檯/打開圖形顯示管理的7號控制檯

同時在上述過程中各階段所需要讀取的文件和操作的對象:
BIOS啓動引導階段                          GRUB啓動引導階段                    內核階段                            /init/sysinit階段
==================================================================================================
None                                         /boot/grub/grub.conf               /boot/vmlinuz-<version>      /etc/rc.d/rc.sysinit
                                                /boot/grub/stage1_5               /boot/initrd-<version>         /etc/inittab
                                                /boot/grub/stage2                                                         /etc/rc.d/rc<#>.d
                                                                                                                                 /etc/rc.d/init.d/*
                                                                                                                                             



(下面是詳細的過程)                                                                                                                     
第一階段:
系統上電開機後,主板BIOS(Basic Input / Output System)運行POST(Power on self test)代碼,檢測系統外圍關鍵設備(如:CPU、內存、顯卡、I/O、鍵盤鼠標等)。硬件配置信息及一些用戶配置參數存儲在主板的CMOS( Complementary Metal Oxide Semiconductor)上(一般64字節),實際上就是主板上一塊可讀寫的RAM芯片,由主板上的電池供電,系統掉電後,信息不會丟失。
執行POST代碼對系統外圍關鍵設備檢測通過後,系統啓動自舉程序, 根據我們在BIOS中設置的啓動順序搜索啓動驅動器(比如的硬盤、光驅、網絡服務器等)。選擇合適的啓動器,比如通常情況下的硬盤設備,BIOS會讀取硬 盤設備的第一個扇區(MBR,512字節),並執行其中的代碼。實際上這裏BIOS並不關心啓動設備第一個扇區中是什麼內容,它只是負責讀取該扇區內容、 並執行,BIOS的任務就完成了。此後將系統啓動的控制權移交到MBR部分的代碼。
注: 在我們的現行系統中,大多關鍵設備都是連在主板上的。因此主板BIOS提供了一個操作系統(軟件)和系統外圍關鍵設備(硬件)最底級別的接口,在這個階段,檢測系統外圍關鍵設備是否“準備好”,以供操作系統使用。

第二階段:
BIOS通過下面兩種方法之一來傳遞引導記錄:
第一,        將控制權傳遞給initial program loader(IPL),該程序安裝在磁盤主引導記錄(MBR)中
第二,        將控制權傳遞給initial program loader(IPL),該程序安裝在磁盤分區的啓動引導扇區中
無論上面的哪種情況中,IPL都是MBR的一部分並應該存儲於一個不大於446字節的磁盤空間中,因爲MBR是一個不大於512字節的空間。
因此IPL僅僅是GRUB的第一個部分(stage1),他的作用就是定位和裝載GRUB的第二個部分(stage2);stage2對啓動系統起關鍵作 用,該部分提供了GRUB啓動菜單和交互式的GRUB的shell。啓動菜單在啓動時候通過/boot/grub/grub.conf文件所定義的內容生 成。在啓動菜單中選擇了kernel之後,GRUB會負責解壓和裝載kernel image並且將initrd裝載到內存中。最後GRUB初始化kernel啓動代碼。
完成之後後續的引導權被移交給kernel。

假設Boot Loader爲grub (grub-0.97),其引導系統的過程如下:
grub分爲stage1 (stage1_5) 和stage2兩個階段。stage1可以看成是initial program loaderI(IPL),而stage2則實現了grub的主要功能,包括對特定文件系統的支持(如ext2,ext3,reiserfs 等),grub自己的shell,以及內部程序(如:kernrl,initrd,root)等。
stage 1:MBR(512 字節,0頭0道1扇區),前446字節存放的是 stage1,後面存放硬盤分區表信息,BIOS將stag1載入內存中0x7c00處並跳轉執行。stage1(/stage1/start.S)的任 務非常單純,僅僅是將硬盤0頭0道2扇區讀入內存。0頭0道2扇區內容是源代碼中的/stage2/start.S,編譯後512字節,它是stage2 或者stage1_5的入口。
注:此時stage1是沒有能力識別文件系統的,其定位硬盤0頭0道2扇區過程如下:
BIOS將stage1載入內存0x7c00處並執行,然後調用BIOS INIT13中斷,將硬盤0頭0道2扇區內容載入內存0x7000處,然後調用copy_buffer將其轉移到內存0x8000處。定位0頭0道2扇區有兩種尋址方式:LBA、CHS。
start.S的主要功能是將stage2或stage1_5從硬盤載入內存,如果是stage2,則載入0x820處;如果是 stage1_5,則載入0x2200處。
注:這裏的stage2或者stage1_5不是/boot分區/boot/grub目錄下的文件,這個時候grub還沒有能力識別任何文件系統。分以下兩種情況:
(1)假如start.S讀取的是stage1_5,它存放在硬盤0頭0道3扇區向後的位置,stage1_5作爲stage1和stage2中間的橋 樑,stage1_5有識別文件系統的能力,此後grub纔有能力去訪問/boot分區/boot/grub目錄下的 stage2文件,將stage2載入內存並執行。
(2)假如start.S讀取的是stage2,同樣,這個stage2也不是/boot分區/boot/grub目錄下的stage2,這個時候 start.S讀取的是存放在/boot分區Boot Sector的stage2。這種情況下就有一個限制:因爲start.S通過BIOS中斷方式直接對硬盤尋址(而非通過訪問具體的文件系統),其尋址範 圍有限,限制在8GB以內。因此這種情況需要將/boot分區分在硬盤8GB尋址空間之前。
假如是情形(2),我們將/boot/grub目錄下的內容清空,依然能成功啓動grub;假如是情形(1),將/boot/grub目錄下stage2刪除後,則系統啓動過程中grub會啓動失敗。
這個地方經常要進行的操作:
是關於grub常用的幾個指令對應的函數:
grub>root (hd0,0)                                                                                                --root指令爲grub指定了一個根分區
grub>kernel /xen.gz-2.6.18-37.el5                                                                          --kernel指令將操作系統內核載入內存
grub>module /vmlinuz-2.6.18-37.el5xen ro root=/dev/sda2                                          --module指令加載指定的模塊
grub>module /initrd-2.6.18-37.el5xen.img                                                                 --指定initrd文件
grub>boot                                                                                                          --boot 指令調用相應的啓動函數啓動OS內核


第三階段:
如階段2所述,grub>boot指令後,系統啓動的控制權移交給kernel。Kernel會立即初始化系統中各設備並做相關配置工作,其中包括CPU、I/O、存儲設備等。
關於設備驅動加載,有兩部分:一部分設備驅動編入Linux Kernel中,Kernel會調用這部分驅動初始化相關設備,同時將日誌輸出到kernel message buffer,系統啓動後dmesg可以查看到這部分輸出信息。另外有一部分設備驅動並沒有編入Kernel,而是作爲模塊形式放在 initrd(ramdisk)中。
在2.6內核中,支持兩種格式的initrd,一種是2.4內核的文件系統鏡像image-initrd,一種是cpio格式。以 cpio 格式爲例,內核判斷initrd爲cpio的文件格式後,會將initrd中的內容釋放到rootfs中。
initrd是一種基於內存的文件系統,啓動過程中,系統在訪問真正的根文件系統/時,會先訪問initrd文件系統。將initrd中的內容打開來看, 會發現有bin、devetc、lib、procsys、sysroot、init等文件(包含目錄)。其中包含了一些設備的驅動模塊,比如scsi ata等設備驅動模塊,同時還有幾個基本的可執行程序 insmod, modprobe, lvm,nash。主要目的是加載一些存儲介質的驅動模塊,如上面所說的scsi ideusb等設備驅動模塊,初始化LVM,把/根文件系統以只讀方式掛載。
initrd中的內容釋放到rootfs中後,Kernel會執行其中的init文件,這裏的init是一個腳本,由nash解釋器執行。這個時候內核的控制權移交給init文件處理,我們查看init文件的內容,主要也是加載各種存儲介質相關的設備驅動。
驅動加載後,會創建一個根設備,然後將根文件系統/以只讀的方式掛載。這步結束後釋放未使用內存並執行switchroot,轉換到真正的根/上面去,同 時運行/sbin/init程序,開啓系統的1號進程,此後系統啓動的控制權移交給 init 進程。關於switchroot是在nash中定義的程序。
Linux Kernel需要適應多種不同的硬件架構,但是將所有的硬件驅動編入Kernel又是不實際的,而且Kernel也不可能每新出一種硬件結構,就將該硬件 的設備驅動寫入內核。實際上Linux Kernel僅是包含了基本的硬件驅動,在系統安裝過程中會檢測系統硬件信息,根據安裝信息和系統硬件信息將一部分設備驅動寫入 initrd 。這樣在以後啓動系統時,一部分設備驅動就放在initrd中來加載。

第四階段:
init進程起來後,系統啓動的控制權移交給init進程。
/sbin/init進程是所有進程的父進程,當init起來之後,它首先會讀取配置文件/etc/inittab,進行以下工作:
1)執行系統初始化腳本(/etc/rc.d/rc.sysinit),對系統進行基本的配置,以讀寫方式掛載根文件系統及其它文件系統,到此係統基本算運行起來了,後面需要進行運行級別的確定及相應服務的啓動;
2)確定啓動後進入的運行級別;
3) 執行/etc/rc.d/rc,該文件定義了服務啓動的順序是先K後S,而具體的每個運行級別的服務狀態是放在/etc/rc.d/rcn.d(n=0~6)目錄下,所有的文件均鏈接至/etc/init.d下的相應文件。
4)有關key sequence的設置
5) 有關UPS的腳本定義
6)啓動虛擬終端/sbin/mingetty
7)在運行級別5上運行X
這時呈現給用戶的就是最終的登錄界面。
至此,系統啓動過程完畢:)
說明:
1)/etc/rc.d/rc.sysint -- System Initialization Tasks
它的主要工作有:
配置selinux,
系統時鐘,
內核參數(/etc/sysctl.conf),
hostname,
啓用swap分區,
根文件系統的檢查和二次掛載(讀寫),
激活RAID和LVM設備,
啓用磁盤quota
檢查並掛載其它文件系統
等等。

GRUB的基本原理以及對GRUB的操作控制方法:
GRUB全稱爲Grand Unified Boot Loader,是Linux操作系統主流的啓動引導管理器。主要作用是啓動和裝載Linux操作系統。系統啓動過程中一旦完成了BIOS自檢,GRUB會 被立刻裝載。在GRUB裏面包含了可以載入操作系統的代碼以及將操作系統引導權傳遞給其他啓動引導管理器的代碼。GRUB可以允許用戶選擇使用不同的 kernel啓動系統,或者在啓動系統的過程中設置不同的啓動參數。
而通常BIOS會以下面兩種方法之一來調用啓動引導管理器:
將控制權移交給於驅動器主引導記錄的initial program loader(IPL);
將控制權移交給其他啓動引導管理器,再由他們將控制權移交給安裝在分區引導扇區的IPL
通常情況下啓動引導管理器GRUB由兩部分組成(stage1和stage2):
stage1比較小,通常可以駐留在MBR或者各個磁盤分區的啓動扇區中,主要作用是裝載stage2。
stage2比較大,從磁盤的啓動引導分區讀取
至於在stage1和stage2之間存在一個stage1.5,是因爲starge1.5具有識別文件系統的能力。
在Linux系統中對GRUB的配置有兩種方法:
主要引導管理器:
會將啓動引導管理器的stage1安裝在MBR上,這時啓動引導管理器必須被配置爲可以傳遞控制權到其他操作系統;
次要引導管理器:
會將啓動引導管理器的stage1安裝在一些分區的引導扇區上,而其他的啓動引導管理器會被安裝在MBR上,由他們來向Linux啓動引導管理器傳遞控制權。
GRUB在啓動過程中可以提供命令行交互界面,可以從ext系列,reiserfs,fat等多種文件系統引導系統,並且可以提供密碼加密功能,其內容在 /boot分區下,系統啓動過程中由配置文件/boot/grub/grub.conf來定義啓動方式,對該配置文件的更改會立即生效。
在配置文件/boot/grub/grub.conf文件中定義的內容包括:
grub所在的分區,引導系統所使用的kernel文件位置,硬件初始化使用的initrd文件位置,以及啓動參數。
例如:
grub>root (hd0,0)                                                                                         --root指令爲grub指定了一個根分區
grub>kernel /xen.gz-2.6.18-37.el5                                                                   --kernel指令將操作系統內核載入內存
grub>module /vmlinuz-2.6.18-37.el5xen ro root=/dev/sda2                                   --module指令加載指定的模塊
grub>module /initrd-2.6.18-37.el5xen.img                                                          --指定initrd文件
grub>boot                                                                                                   --boot 指令調用相應的啓動函數啓動OS內核

可見其指定的內容大多數在/boot分區,如果切換到/boot分區之後會看到這些內容:
/boot/vmlinuz-*                 linux kernel的一個copy;
/boot/initrd*.img                初始化的ram disk文件
/boot/grub/device.map        linux設備名和grub設備名的映射文件
/boot/grub/grub.conf          主配置文件

通常GRUB出錯機率不是很大,但一旦出現問題恐怕採用最多的方式是重裝grub到MBR中。
在這種時候需要注意的問題有:
首先,設備映射關係:
GRUB裏面對設備名稱的定義和系統中對設備名稱的定義方法不一樣:
        (fd0)                /dev/fd0
        (hd0)                /dev/sda        /dev/hda
        (hd1)                /dev/sdb        /dev/hdb
如夠進入系統或者救援模式,可執行命令/sbin/grub-install /dev/sda(或者hda)進行GRUB重裝:
        # /sbin/grub-install device
處於某種原因MBR中信息出錯可以使用上面的命令將其重裝到磁盤主引導記錄中;但是如果在不能進入系統的情況下就需要通過grub的命令行界面進行手動設置,這個時候就要注意上面所提到的映射關係。

同時,在grub命令行中對grub進行手動設置的時候需要注意所使用的命令:
        # root (hd0,0)                                --指定啓動分區
        # setup(hd0)                                  --表示將grub安裝在主引導記錄上
        # quit                                              --退出grub        shell

下面是一個完整的grub.conf文件內容:
[root@dhcp-0-195 ~]# cat /etc/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/VolGroup001/LogVol00
#          initrd /initrd-version.img
#boot=/dev/sda
default=0
timeout=30
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
password --md5 $1$apEcJWbA$DTJ8a6mKn/3yrTTSXBtdH0
title Red Hat Enterprise Linux Client (2.6.18-8.1.1.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-8.1.1.el5 ro root=/dev/VolGroup001/LogVol00 crashkernel=128M@16M
        initrd /initrd-2.6.18-8.1.1.el5.img

系統啓動運行級別的概念以及服務的定製方法;
當initrd可以正常檢測和裝載之後,最後的工作就基本上由操作系統來進行了。當系統的init進程起來之後系統啓動的控制權移交給init進程。
/sbin/init進程是所有進程的父進程,當init起來之後,它首先會讀取配置文件/etc/inittab,進行以下工作:
1)執行系統初始化腳本(/etc/rc.d/rc.sysinit),對系統進行基本的配置,以讀寫方式掛載根文件系統及其它文件系統,後面需要進行運 行級別的確定及相應服務的啓動,(從這個角度可以看出如果要定義系統的init動作,需要修改/etc/rc.d/rc.sysinit腳本)
2)通過對/etc/inittab文件的讀取確定啓動後進入的運行級別;
3) 在相應的運行級別中執行/etc/rc.d/rcx.d目錄下的腳本名稱,該文件定義了服務啓動的順序是先K後S,而具體的每個運行級別的服務狀態是放在 /etc/rc.d/rcn.d(n=0~6)目錄下,但這些文件均是到/etc/init.d下的相應文件的鏈接。
系統會按照在該目錄下的文件名稱和優先級執行對應運行級別目錄下的腳本:
在某個運行級別的對應目錄下,K開頭的服務被關閉,S開頭的服務被開啓,K在S開始之前執行,在執行過程中按照數字來定義優先級,數字越低優先級越高。
4)按照/etc/rc.d/rcX.d目錄中的定義,系統會於後臺啓動相應的服務,如果要對某個運行級別中的服務進行更具體的定製,通過chkconfig命令來操作,或者通過setup/ntsys/system-config-services來進行定製。
5)在/etc/inittab文件中存在有關key sequence,UPS的腳本定義,啓動虛擬終端/sbin/mingetty的設置,這時呈現給用戶的就是最終的登錄界面。
也就是說後臺啓動的服務完畢之後,如果系統默認進入字符界面,則運行mgetty進入1-6號終端控制檯,如果系統默認進入圖形界面,則開啓gdm服務進入7號虛擬圖形控制檯。
至此,系統啓動過程完畢。

對於/etc/rc.d/rc.sysinit文件的說明:
/etc/rc.d/rc.sysint -- System Initialization Tasks 執行系統初始化任務的腳本。
它的主要工作有:
配置selinux,
系統時鐘,
內核參數(/etc/sysctl.conf),
hostname,
啓用swap分區,
根文件系統的檢查和二次掛載(讀寫),
激活RAID和LVM設備,
啓用磁盤quota
檢查並掛載其它文件系統

這是其基本要實現的工作內容:
#!/bin/bash
#
# /etc/rc.d/rc.sysinit - run once at boot time
#
# Taken in part from Miquel van Smoorenburg's bcheckrc.


# Check SELinux status
               
# Because of a chicken/egg problem, init_crypto must be run twice.  /var may be
# encrypted but /var/lib/random-seed is needed to initialize swap.

# Only read this once.

# Initialize hardware

# Set default affinity

# Load other user-defined modules

# Load modules (for backward compatibility with VARs)

# Start the graphical boot, if necessary; /usr may not be mounted yet, so we
# may have to do this again after mounting

# Configure kernel parameters

# Set the hostname.

# Initialize ACPI bits

# RAID setup

# Device mapper & related initialization

# Update quotas if necessary

# Remount the root filesystem read-write.

# Clean up SELinux labels

# Clear mtab

# Remove stale backups

# Enter mounted filesystems into /etc/mtab

# Mount all other filesystems (except for NFS and /proc, which is already
# mounted). Contrary to standard usage,
# filesystems are NOT unmounted in single user mode.

# Check to see if a full relabel is needed

# Start the graphical boot, if necessary and not done yet.

# Initialize pseudo-random number generator

# Use the hardware RNG to seed the entropy pool, if available

# Configure machine if necessary.

# Clean out /.

# Do we need (w|u)tmpx files? We don't set them up, but the sysadmin might...

# Clean up /var.  I'd use find, but /usr may not be mounted.

# Reset pam_console permissions

# Clean up utmp/wtmp

# Clean up various /tmp bits

# Make ICE directory

# Start up swapping.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章