12.2. FreeBSD 開機程序

打開電腦並啟動作業系統的這個動作呈現了一個有趣的困境。照道理,電腦在啟動作業系統之前並不知道要如何做任何事情,這些事情之中包括從磁碟執行程式。如果電腦無法在沒有作業系統的情況下執行程式,而作業系統的程式本身又在磁碟上,那麼作業系統要如何啟動呢?

這個問題如同 The Adventures of Baron Munchausen 一書中的一個角色掉進了洞裡,他抓住了靴子上的拔靴帶 (Bootstrap) 才把自己拉了出來,因此在早期電腦領域用 bootstrap 一詞來指載入作業系統的機制,後來被縮短為 booting

在 x86 硬體上,基本輸入/輸出系統 (Basic Input/Output System, BIOS) 負責載入作業系統。 BIOS 會找到硬碟上的主開機記錄區 (Master Boot Record, MBR),該記錄區必須位於磁碟上的特定位置。BIOS 有足夠的知識可以載入並執行這個 MBR,並且假設這個 MBRBIOS 的協助下可以完成接下來載入作業系統的工作。

注意:

FreeBSD 在較舊的 MBR 標準與較新的 GUID 分割區表 (GUID Partition Table, GPT) 上都能夠開機 (Booting)。GPT 磁碟分割通常會在有支援統一可延伸韌體介面 (Unified Extensible Firmware Interface, UEFI) 的電腦上找到。不論如何,FreeBSD 即使在只有傳統 BIOS 的機器上,也可以使用 gptboot(8)GPT 分割區開機。直接使用 UEFI 開機的開發工作正在進行中。

MBR 中的程式通常會稱作開機管理程式 (Boot manager),特別是那些會與使用者互動的程式。開機管理程式通常會另一部份的程式會存放於磁碟的第一個磁軌或檔案系統。開機管理程式的例子有標準 FreeBSD 開機管理程式 boot0 又稱 Boot Easy 以及 Grub 常用於各種 Linux® 發行版。

若只有安裝一個作業系統,MBR 會搜尋磁碟上第一個可開機的 (使用中) 切割區 (Slice),然後執行在該切割區上的程式來載入剩下的作業系統。當有多個作業系統存在時,可以安裝可顯示作業系統清單的開機管理程式,以讓使用者可以選擇要啟動的作業系統。

剩餘的 FreeBSD 開機系統分成三個階段,第一個階段只知道如何讓電腦進入特定狀態並執行第二階段,第二個階段在執行第三階段之前會做的事比較多一點,第三個階段會完成載入作業系統的工作。把工作分成三個階段的原因是 MBR 有限制在階段一與階段二能夠執行程式的大小。將這些工作連結在一起讓 FreeBSD 能夠提供更有彈性的載入程式。

核心會接著開始偵測裝置並初始化這些裝置供使用。核心開機程序完成之後,核心便會傳送控制權給使用者程序 init(8),這個程序會確保磁碟在可以使用的狀態,然後啟動使用者層級的資源設置來掛載檔案系統、設定網路卡以能夠連線網路、啟動那些被設定在開機時要啟動的程序。

本章節將更詳細介紹這些階段並示範如何與 FreeBSD 開機程序互動。

12.2.1. 開機管理程式

有時會稱在 MBR 中的開機管理程式為開機程序的 第零階段 (Stage zero),FreeBSD 預設會使用 boot0 開機管理程式。

由 FreeBSD 安裝程式所安裝的 MBR 便是以 /boot/boot0 為基礎。boot0 的大小與容量被限制在 446 個位元組是由於切割表與 0x55AA 識別碼位於 MBR 的最末端。若安裝多個作業系統使用 boot0 ,則會在開機時顯示如下範例的訊息:

範例 12.1. boot0 螢幕截圖
F1 Win
F2 FreeBSD

Default: F2

其作他作業統若在 FreeBSD 之後才安裝則會覆蓋現有的 MBR,若這件事發生了,或者要使用 FreeBSD MBR 取代現有的 MBR 可使用以下指令:

# fdisk -B -b /boot/boot0 device

其中 device 開機磁碟,例如第一個 IDE 磁碟為 ad0,第二個 IDE 控制器的第一個 IDE磁碟為 ad2,第一個 SCSI 磁碟為 da0。要建立自訂的 MBR 設定請參考 boot0cfg(8)

12.2.2. 階段一與階段二

概念上,第一與第二個階段均為磁碟上同一個區域上同一個程式的一部份,由於空間上的限制,它們被分成兩部份,但是會一併安裝。它們會由 FreeBSD 安裝程式或 bsdlabel/boot/boot 複製而來。

這兩個階段均位於檔案系統之外,在開機切割區的第一個磁軌,從第一個磁碟扇區 (Sector) 開始,這個位置便是 boot0 或其他開機管理程式所會儲存的地方,並會尋找可以執行的程式以繼續開機程序。

第一個階段的 boot1 非常的簡單,因為它只能有 512 位元組的大小。它只能認得儲存切割區資訊的 FreeBSD bsdlabel 以及尋找並執行 boot2

階段二 boot2 稍微複雜一點,能夠理解 FreeBSD 檔案系統來搜尋檔案。它可以提供一個簡單的介面來選擇要執行的核心或載入程式。它所執行的載入程式 (loader) 更複雜並能讀取開機設定檔。若開機程序在階段二中斷,則會顯示以下的互動畫面:

範例 12.2. boot2 螢幕截圖
>> FreeBSD/i386 BOOT
Default: 0:ad(0,a)/boot/loader
boot:

要更換已安裝的 boot1boot2 可使用 bsdlabel,其中 diskslice 是要開機的磁碟與切割區,例如 ad0s1 代表第一個 IDE 磁碟的第一個切割區:

# bsdlabel -B diskslice

警告:

若只使用磁碟名稱,如 ad0bsdlabel 便會以 危險專用的模式 來建立磁碟,而不會建立任何分割區。這個可能與預期的動作不同,所以在按下 Return 鍵之前請再次確認 diskslice

12.2.3. 階段三

loader 是三階段開機程多的最後一個階段,載入程式位於檔案系統之中,通常在 /boot/loader

loader 主要目地是利用擁有更複雜指令集的強大直譯器做為基礎的內建指令集提供一個互動的方式來做設定。

在初始化的過程中,loader 會偵測 Console 與磁碟,並找出可以用來開機的磁碟。在由 Script 或互動輸入使用者指令的地方會設定相對的變數並啟動直譯器。

loader 接著會讀取 /boot/loader.rc,這個程式預設又會讀取 /boot/defaults/loader.conf 來設定合理的變數預設值以及讀取 /boot/loader.conf 來對這些變數做本地的更改。loader.rc 接著會依這些變數來運作,讀取選擇模組與核心。

最後,預設情況下 loader 會待候鍵盤輸入 10 秒鐘,若沒有被中斷的話會接著啟動核心。若被使用者中斷,則會向使用者顯示提示字元,此時使用可以使用指令集來調整變數、卸載所有模組、載入模組,然後最後開機或重新開機。表格 12.1, “載入程式內建指令” 中列出了最常使用的 loader 指令。要完整了解所有可用的指令,請參考 loader(8)

表格 12.1. 載入程式內建指令
變數說明
autoboot seconds若在指定時間 (秒) 內沒有中斷,會繼續啟動核心。此指令會顯示倒數,預設的時間為 10 秒鐘。
boot [-options] [kernelname]使用任何指定的選項或核心名稱立即啟動核心,要由指令列指定核心名稱必須先執行 unload,否則會使用先前載入過的核心。若 kernelname 不是完整的路徑則會搜尋 /boot/kernel/boot/modules 底下。
boot-conf依據指定的變數及最常用的 kernel 再做一次相同的自動模組設置。這只有在執行 unload 之後,尚未變更變數之前方可使用。
help [topic]顯示自 /boot/loader.help 取得的說明訊息。若指定的主題為 index 則會顯示所有可用的主題。
include filename讀取指定的檔案並直譯每一行。若有錯誤則會立即中止 include
load [-t type] filename由指定的檔案名稱載入核心、核心模組或指定類型的檔案。任何於 filename 之後的參數都會被傳遞到該檔案。若 filename 不是絕對位置則會搜尋 /boot/kernel/boot/modules 底下。
ls [-l] [path]顯示指定路徑中的檔案,若未指定路徑則會顯示根目錄中的檔案。若有指定 -l,則會連檔案大小一同顯示。
lsdev [-v]列出所有的裝置,這些裝置可能可以用來載入模組。若有指定 -v 則會顯示更詳細的資訊。
lsmod [-v]顯示已載入的模組。若有指定 -v 則會顯示更詳細的資訊。
more filename顯示指定的檔案,並於每 LINES 行顯示後會暫停。
reboot立即重新啟動系統。
set variable, set variable=value設定指定的環境變數。
unload移除所有已載入的模組。

這裡有一些 loader 用法的實務範例。要使用一般的核心開機進入單使用者模式 (Single-user mode) 可:

boot -s

要卸載一般的核心與模組,然後載入先前或另一個指定的核心可:

unload
load kernel.old

使用 kernel.GENERIC 來代表安裝程式使用的預設核心,或 kernel.old 來代表在系統升級之前或設定自訂核心前安裝的核心。

使用以下指令來使用另一個核心載入一般的模組:

unload
set kernel="kernel.old"
boot-conf

要載入一個已自動化的核心設置 Script 可:

load -t userconfig_script /boot/kernel.conf

12.2.4. 最終階段

loader 或由會繞開 loaderboot2 載入核心之後,載入程式便會檢查是不有使用任何開機旗標,並根據需要調整開機的方式。表格 12.2, “開機時核心互動參數” 列出了常用的開機旗標,請參考 boot(8) 取得更多其他開機旗標的資訊。

表格 12.2. 開機時核心互動參數
項目說明
-a核心初始化時,會詢問要掛載為根檔案系統的裝置。
-CCDROM 做為根檔案系統開機。
-s開機進入單使用者模式。
-v核心啟動時提供更多詳細資訊。

一旦核心完成開機程序後,便會傳送控制權給使用者程序 init(8),該程序位於 /sbin/init 或在 loader 中的 init_path 變數所指的程式路徑。這是開機程序的最後一個階段。

開機程序會確保系統上的檔案系統的一致性 (Consistency),若 UFS 檔案系統不一致且 fsck 無法修時,init 會讓系統進入單使用者模式,以讓系統管理者能夠直接解決問題,否則系統會開機進入多使用者模式。

12.2.4.1. 單使用者模式

使用者可以在開機時指定 -s 或在 loader 設定 boot_single 變數進入這個模式。也可以透過在多使用者模式執行 shutdown now 進入此模式。進入單使用者模式時會出現此訊息:

Enter full pathname of shell or RETURN for /bin/sh:

若使用者按下 Enter,系統便會進入預設的 Bourne shell。要指定使用其他的 Shell 則輸入該 Shell 的完整路徑。

單使用者模式通常用來修復因檔案系統不一致或開機設定檔發生錯誤造成的無法開機,也可以用來重設遺忘的 root 的密碼,因為在單使用者模式會給予對本地系統及設定檔完整的存取權。在這個模式下沒有網路功能。

雖然單使用者模式對修復系統很有幫助,但若系統放在不安全的場所便會有安全上的風險。預設,開機進入單使用者模式後,任何能夠存取實體主機的使用者便擁有系統的完整控制權。

若在 /etc/ttys 系統 console 更改為 insecure,系統便會在初始化單使用者模式前先詢問 root 的密碼。這可增加一定程度的安全性,但便無法在忘記 root 密碼時重設密碼。

範例 12.3. 在 /etc/ttys 設定不安全的 Console
# name  getty                           type    status          comments
#
# If console is marked "insecure", then init will ask for the root password
# when going to single-user mode.
console none                            unknown off insecure

不安全 (insecure) console 代表對 Console 的實體安全性評估為不安全 (insecure),所以只有知道 root 密碼的人可以使用單使用者模式。

12.2.4.2. 多使用者模式

init 正常找到檔案系統或在單使用者模式的使用者完成了操作並輸入 exit 離開單使用者模式,系統便會進入多使用者模式,在這個模式便會開始系統的資源設置。

資源設置系統 (Resource configuration system) 會從 /etc/defaults/rc.conf 讀取設定預設值以及從 /etc/rc.conf 讀取系統特定的設定,接著會繼續掛載系統列於 /etc/fstab 的檔案系統,也會啟動網路服務、其他的系統 Daemon,然後執行本地已安裝套件的啟動 Script。

要了解更多有關資源設置系統,請參考 rc(8) 以及查看位於 /etc/rc.d 的 Script。

本文及其他文件,可由此下載: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/

若有 FreeBSD 方面疑問,請先閱讀 FreeBSD 相關文件,如不能解決的話,再洽詢 <questions@FreeBSD.org>。

關於本文件的問題,請洽詢 <doc@FreeBSD.org>。