透徹的了解Linux啟動流程是非常關鍵的知識點,只有了解了這部分內容,才會在Linux出現系統級別的錯誤時能夠非常冷靜的面對以及快速的排錯。
Linux啟動流程
第一階段
- BIOS不是操作系統的職責范圍
- BIOS是硬件的功能,屬於firmware
- BIOS存儲於ROM,不需要強電就可以實現數據保存
- 更改BIOS如啟動順序保存在一種特定的RAM中,為了保證斷電后實際更改保存,通過BIOS上加電池來解決
- 在BIOS可以選擇啟動順序(硬盤,光盤,網絡等)
- 如果選擇BIOS從硬盤啟動,硬盤的必須是MBR分區,相應的支持的硬盤最大為2TB
- 替代BIOS的是UEFI(Unified Extensible Firmware Interface),通常配合硬盤分區類型GPT,支持最大硬盤8ZB
- 一旦BIOS找到硬盤MBR分區中的引導程序bootloader,就把后續工作轉交給bootloader
第二階段
- bootloader把內核加載到內存
- 但凡讀取了一個設備的MBR,如果MBR中的bootloader損壞,無法正常啟動,操作系統不會再去讀第二個設備的MBR,這也正是由於bootloader損壞,我們需要更改BIOS的啟動順序從光盤啟動去修復硬盤中bootloader的原因
- 一旦Kernel裝載完畢,Bootloader退出工作,把后續的工作交給Kernel
Bootloader詳解:
Bootloader是一個程序,不屬於任何的操作系統,但是由操作系統安裝時提供。常見的有微軟的ntloader,Linux的兩種常用的bootloader:
- LILO:大於8G的硬盤不支持,在嵌入式系統中常用
- GRUB:GRand Unified Bootloader,目前有兩個主流版本grub-0.97和grub2-2.02,下圖就是在安裝Linux過程中創建bootloader的過程
GRUB三個階段詳解:
GRUB是一個程序,需要安裝在MBR分區的bootloader位置上來引導操作系統的啟動,MBR446bytes的空間沒有辦法展示GRUB的豐富的特性,由此引入GRUB三階段概念。
GRUB Stage1:MBR
作用:引導GRUB的第二階段
GRUB Stage1.5:
作用:識別常見的不同類型的文件系統,mbr之后的扇區,讓stage1中的bootloader能識別stage2所在的分區上的文件系統
GRUB stage2:
作用:位於內核所在的分區的/boot/grub/stage2,借助grub.conf配置文件,來實現更強大的功能
grub.conf詳解:
default=0 : 設定默認啟動的title編號,從0開始
timeout=5 : 等待用戶選擇的超時時長,單位是秒
splashimage : grub的背景圖片
hiddenmenu : 隱藏菜單(刪除之后不再隱藏)
title : 內核標題或操作系統標識,字符串,可自由修改
root (hd0,0) : 內核文件所在的設備,對grub而言,所有硬盤類型一率為hd,hd#表示第幾個磁盤,最后的0表示對應磁盤的分區格式為(hd#,N)常見的主分區0,1,2,3
kernel : 內核文件的路徑,及傳遞給內核的參數(和cat /proc/cmdline內容一樣);注意:此路徑是指GRUB訪問的路徑,而不是文件系統訪問的路徑
kernel /vmlinuz-2.6.32-696.el6.x86_64 表示的是boot單獨掛載在一個分區上
kernel /boot/vmlinuz-2.6.32-696.el6.x86_64 表示的是boot和根掛載在同一個分區
initrd : initramfs文件及路徑,是一個小的完整意義上的linux,是安裝Linux操作系統的最后一步通過動態收集內核為了訪問根文件系統所在設備必要的驅動
initrd /initramfs-2.6.32-696.el6.x86_64.img
第三階段
- 內核Kernel要執行/sbin/init,就必須能夠先訪問根文件系統,因為在Linux下,文件系統從根/目錄開始,就是根文件系統rootfs
- Linux是單內核結構
- 內核本身要盡可能的小,因為內核是常駐內存的,同時內核要盡可能多的支持各種類型的硬件,支持更多的類型硬件意味着內核就會變大,占用更多的內存空間,解決方法:通過模塊化的設計.ko來實現內核模塊的動態裝載和卸載,模塊不僅包括驅動程序,也可以包括文件系統,加密功能等
- Linux內核有兩部分組成,核心和外圍模塊。初始化時只是核心本身,外圍模塊在/lib/modules/“內核版本號命名的目錄"/
- Linux內核名稱: `uname -r` 2.6.32-696.el6.x86_64 內核文件:vmlinuz-2.6.32-696.el6.x86_64 ,模塊所在的目錄/lib/modules/2.6.32-696.el6.x86_64,如果是多內核的安裝方式,可以在/boot目錄下看到多個內核文件vmlinuz_*以及在/lib/modules/下的多個和內核同名稱的文件夾
- 在/boot目錄下還有一個以initramfs-2.6.32-696.el6.x86_64.img文件,這個文件是在安裝完操作系統的過程中通過腳本或命令生成的,動態收集內核為了訪問根所在的設備需要的驅動程序,並且生成initramfs-2.6.32-696.el6.x86_64.img文件
- initramfs-2.6.32-696.el6.x86_64.img專業名稱:偽根文件系統,起臨時過渡的作用,由bootloader裝載到內存,把內存模擬成磁盤用(ramfs),因為initramfs-2.6.32-696.el6.x86_64.img文件中已經完全包含了rootfs根文件系統的驅動,所以內核通過initramfs來訪問根文件系統,從而找到/sbin/init來啟動用戶空間的第一個進程可以100%成功
- bootloader能訪問的分區,一定是一個基本的磁盤設備,內核Kernel也一定能識別和訪問,內核Kernel和initramfs都是由bootloader裝載的,所以兩個文件必須位於同一個磁盤設備同一分區
第四階段
- 在CentOS6中,/sbin/init同時讀取/etc/inittab和/etc/init/*.conf配置文件
- /sbin/init是用戶空間的第一個進程,管理所有用戶空間的進程,除非要調用硬件,才會切換到內核空間
- CentOS7此名字是systemd
- 運行系統初始化腳本/etc/rc.d/rc.sysinit
- 運行/etc/rc.d/rc腳本,此腳本作用是根據所選擇的運行級別作為位置參數,然后去觸發運行rc.{0..6}.d下的以K*和S*開頭的腳本,K*表示kill,S*表示start目錄/etc/rc.d/init.d下的服務腳本。K*和S*以軟鏈接的方式對應/etc/rc.d/init.d下的服務腳本。
- 運行/etc/rc.d/rc.local腳本,此腳本可以運行用戶自開發的初始化腳本
- 執行/bin/login程序,等待用戶登錄
- 最后一步,登錄之后開始以Shell控制主機
Linux啟動失敗及恢復方法
GRUB stage1失敗情形:破壞bootloader所在的分區
破壞方法:
- 備份MBR dd if=/dev/sda of=/data/mbr bs=1 count=512
- 破壞MBR dd if=/dev/zero of=/dev/sda bs=1 count=446
- 檢查hexdump -C -n 512 /dev/sda -v
- 重啟reboot
啟動故障現象:
恢復方法:
- 進入救援模式
- 找到mbr保存的路徑 /mnt/sysimage/data
- 恢復 dd if=/mnt/sysimage/data/mbr of=/dev/sda bs=1 count=446
- 也可以通過grub-install /dev/sda來恢復,先通過光盤引導救援模式,執行chroot /mnt/sysimage
- 也可以通過grub命令修復,這種修復方法依賴/boot/grub下的部分文件
-
grub> root (hd0,0) :root (hd0,0) Filesystem type is ext2fs, partition type 0x83
-
grub> setup (hd0) : setup (hd0) Checking if "/boot/grub/stage1" exists... yes Checking if "/boot/grub/stage2" exists... yes Checking if "/boot/grub/e2fs_stage1_5" exists... yes Running "embed /boot/grub/e2fs_stage1_5 (hd0)"... 27 sectors are embedded.succeeded Running "install /boot/grub/stage1 (hd0) (hd0)1+27 p (hd0,0)/boot/grub/stage2 / boot/grub/grub.conf"... succeededDone.
- 重啟 reboot
grub命令和grub-install恢復比較:
破壞方法:
- 刪除除grub.conf,splash.xpm.gz之外的所有文件
- 破壞MBR dd if=/dev/zero of=/dev/sda bs=1 count=446
恢復方法:
- 嘗試通過grub命令恢復失敗
- grub> root (hd0,0)root (hd0,0) Filesystem type is ext2fs, partition type 0x83
-
grub> root (hd0,0)
root (hd0,0)
Filesystem type is ext2fs, partition type 0x83
grub> setup (hd0)
setup (hd0)
Checking if "/boot/grub/stage1" exists... no
Checking if "/grub/stage1" exists... noError 15t: File not found
- 此時可以用grub-install /dev/sda可以成功恢復,同時還可以把/etc/grub下的所有文件生成
結論:
- grub命令恢復依賴於/boot/grub的文件
- 對於干凈的系統(沒有做過恢復的系統),/boot/grub下除grub.conf,splash.xpm.gz之外的文件不是系統啟動的必要文件,即刪除這些文件不會影響到系統的啟動
- 一旦使用grub或grub-install做過恢復,/boot/grub下的文件是系統啟動的必要文件,刪除會導致系統無法正常啟動
如下圖就是用grub或grub-install恢復過系統后刪除/boot/grub下除grub.conf,aplash.xpm.gz之外所有文件啟動后的報錯信息
GRUB stage1.5失敗情形:破壞bootloader后續27個扇區所在的分區
破壞方法:
- dd if=/dev/zero of=/dev/sda bs=1 count=10000 skip=512 seek=512
啟動故障現象:
無法自動從光驅啟動,由於512bytes的MBR並沒有被破壞,這也符合我們之前的結論:但凡讀取了一個設備的MBR,如果MBR中的bootloader損壞,無法正常啟動,操作系統不會再去讀第二個設備的MBR
恢復方法:
- 修改BIOS的啟動抗順序,從光驅啟動進入救援模式
- chroot /mnt/sysimage
- 用grub-install命令修復:
- 重啟reboot
GRUB stage2失敗情形:破壞/boot/grub/下的grub.conf文件
破壞方法:
- 刪除/boot/grub下的所有文件
- 重啟系統
啟動故障現象:
恢復方法:
- kernel /vmlinuz-2.6.32-696.el6.x86_64 root=/dev/sda2(此處是指根文件系統所有的分區,而不是boot所在的分區)
- initrd /initramfs-2.6.32-696.el6.x86_64.img
- boot
遺留問題:
對於grub.conf配置文件中如下的內核文件的路徑仍然是疑惑。希望后續隨着知識點的累計能自己解惑。
kernel : 內核文件的路徑,及傳遞給內核的參數(和cat /proc/cmdline內容一樣);注意:此路徑是指GRUB訪問的路徑,而不是文件系統訪問的路徑。
kernel /vmlinuz-2.6.32-696.el6.x86_64 表示boot單獨掛載在一個分區上
kernel /boot/vmlinuz-2.6.32-696.el6.x86_64 表示boot和根掛載在同一個分區