1. 程式人生 > >【Linux】計算機的啟動過程

【Linux】計算機的啟動過程

  計算機啟動是一個非常複雜的過程,大致可以分為四個步驟。  

1.第一階段:BIOS

  BIOS是固化到計算機主機板上一個ROM晶片上的一段程式,這段程式的主要作用有兩個。

1.硬體自檢Power-On Self-Test

  按下電源鍵後,計算機首先會讀取BIOS,然後BIOS檢查計算機硬體有沒有問題,是否滿足執行條件,這個過程叫做“硬體自檢”。如果硬體有問題,電腦上的speaker會發出蜂鳴聲,根據不同的聲音,可以大致判斷那部分硬體出現了問題,比如,電腦按下電源鍵發出短促持續的滴滴聲,很有可能是記憶體條鬆了。如果沒有問題,則會在螢幕上顯示CPU、記憶體、硬碟等硬體資訊。

2.獲得啟動順序,轉交控制權

  硬體自檢通過後,BIOS就要轉交控制權,那麼到底應該交給誰呢?在BIOS當中有一個外部裝置的排序,排在前面的裝置就是優先轉交控制權的裝置。這種排序叫做”啟動順序”(Boot Sequence)。
  
  這就是為什麼用U盤裝系統的時候要將U盤設定為第一啟動項。

2.第二階段:MBR(主引導記錄)

  BIOS根據啟動順序,將控制權轉交給排在第一位的啟動裝置。
  此時,計算機將這個啟動裝置的第一個扇區,即boot sector讀入記憶體。這個扇區的大小是512位元組,這512個位元組可以分為三個部分(參見上一篇文章)。

內容 位元組
MBR 前446位元組
DPT 64位元組
BRID 2位元組

  計算機判斷這512位元組的最後兩個位元組是否為0x55和0xAA。如果是,則表明這個裝置可以用於啟動,如果不是,則將控制權轉交給排在第二位的啟動裝置。重複這個過程,直到找到可以啟動的裝置。
  主引導記錄只有446個位元組,裡面一般裝的是一個引導載入程式(boot loader)(嚴格來講,只是boot loader的主程式),在Linux系統中一般是grub。引導載入程式會在分割槽表中找到活動分割槽(如果某個分割槽記錄的第一個位元組值為0x80,則該分割槽為活動分割槽,0x00表示非活動分割槽),從活動分割槽當中載入核心到記憶體當中來。
  在命令列輸入fdisk -l ,即可檢視那個分割槽是啟用分割槽
  這裡寫圖片描述


在/dev/sda1後面有一個*號,表示這個分割槽是活動分割槽。

3.第三階段:載入核心

  boot loader開始讀取核心檔案後,接下來,Linux就會將核心解壓縮到記憶體當中,並且利用核心的功能開始測試與驅動各個周邊裝置,包括儲存裝置、CPU、網絡卡、音效卡等。此時,Linux核心會重新檢測一次硬體,不一定會用BIOS檢測到的硬體資訊。也就是說,核心此時才開始接管BIOS的工作。核心檔案一般放在/boot當中,名字為/boot/vmlinux.

4.第四階段:執行第一個程序init

  在核心載入完畢進行完硬體檢測和驅動程式載入後,計算機的硬體應該已經準備就緒了。此時,核心會主動呼叫第一個程序,就是/sbin/init。init程序主要工作有下面幾個:

1.獲得執行級別

  init程序首先讀取的檔案是/etc/inittab,獲得執行級別。這個檔案其實只有一句話,就是設定預設的執行級別。
  (centos6和centos5有些區別,centos5的/etc/inittab檔案當中出了設定預設執行級別外,還有其他內容。Centos 6弱化了inittab檔案的作用)
  
inittab檔案的內容如下:

# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
#
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used are:
#   0 - halt (Do NOT set initdefault to this)
#   1 - Single user mode
#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
#   3 - Full multiuser mode
#   4 - unused
#   5 - X11
#   6 - reboot (Do NOT set initdefault to this)
# 
id:3:initdefault:

前面全部都是註釋,只有最後一行設定了預設的執行級別。

2.呼叫/etc/rc.d/rc.sysinit進行系統初始化

  init程序確定了執行級別之後,開始呼叫/etc/rc.d/rc.sysinit指令碼,進行系統初始化,這個指令碼的工作有很多,具體的工作請參看《鳥哥的Linux私房菜》。

3.根據執行級別啟動系統服務

  系統初始化完成後,init程序根據inittab設定的執行級別(假設為N),執行/etc/rcN.d/*目錄下的所有指令碼(其實是連結檔案,真實指令碼在另外一個資料夾)。
  這個目錄下的連結檔案均已K或S開頭,K表示要關閉的服務,S表示要啟動的服務。數字表示執行的順序。

4.執行使用者自定義開機啟動程式(/etc/rc.d/rc.local)

  /etc/rc.d/rc.local這個檔案用於執行使用者自定義的開機啟動程式,如果你想啟動某個指令碼,或執行某項命令,直接將其寫入這個檔案,那麼這個指令碼或命令在計算機啟動時就會被執行。這個檔案預設只有一行。
  這裡寫圖片描述
  就是將/var/lock/subsys/local這個檔案“摸”了一下,沒有改變這個檔案的內容,事實上,這個檔案是空的。摸一下這個檔案僅僅更新了這個檔案的修改時間,即修改時間戳,就是說rc.local的程式已經啟動了, 防止重複執行。
  這裡寫圖片描述
  

5.init執行終端模擬程式mingetty來啟動login程序,最後等待使用者登入。

  至此,計算機總算是啟動了,這個過程真是無比的艱難。