第 3 章 系統初始化

目录

3.1. 啓動過程概述
3.1.1. 第一階段:BIOS
3.1.2. 第二階段:引載加載程序
3.1.3. 第三階段:迷你 Debian 系統
3.1.4. 第四階段:常規 Debian 系統
3.2. SysV 風格的 init
3.2.1. 執行級別的含義
3.2.2. 執行級別的配置
3.2.3. 執行級別管理示例
3.2.4. 每個 init 指令碼預設的引數
3.2.5. 主機名
3.2.6. 檔案系統
3.2.7. 網路介面初始化
3.2.8. 網路服務初始化
3.2.9. 系統訊息
3.2.10. 核心訊息
3.3. udev 系統
3.3.1. 核心模組初始化

作爲系統管理員,粗略地瞭解 Debian 系統的啓動和配置方式是明智的。儘管準確的細節在安裝的軟件包及對應的文檔中,但這些知識對我們大多數人來說都是必須掌握的。

筆者基於自己和其他人的過往及現在的知識,盡己所能地提供關於 Debian 系統的知識要點及其配置的快速概覽作爲讀者的參考。由於 Debian 系統在不斷地更新中,系統的狀況可能已經有所變化。在對系統做任何修改之前,請參考各個軟件包的最新文檔。

[警告] 警告

本章是基於 2013 年發佈的 Debian 7.0 (Wheezy) 編寫的,所以其內容正在變得過時。

計算機系統從上電事件到能爲用戶提供完整的操作系統(OS)功能爲止,需要經歷幾個階段的啓動過程

爲簡便起見,筆者將討論範圍限定在具有默認安裝的典型 PC 平臺上。

典型的啓動過程像是一個四級的火箭。每一級火箭將系統控制權交給下一級。

當然,這些階段可以有不同的配置。比如,你編譯了自己的內核,則可能會跳過迷你 Debian 系統的步驟。因此,在讀者親自確認之前,請勿假定自己系統的情況也是如此。

[注意] 注意

對於 SUN 或 Macintosh 系統等非傳統 PC 平臺來說,ROM 上的 BIOS 及磁盤上的分區可能大不相同(第 9.5.2 节 “硬碟分割槽配置”)。對於這種情況,請另尋對應平臺相關的文檔。

BIOS 是啓動過程的第一階段,在上電事件後開始。CPU 的程序計數器在上電事件後被初始化爲一個特定的內存地址,駐留在只讀存儲器(ROM)中的 BIOS 就是從這個特定的內存地址開始執行。

BIOS 執行硬件的基本初始化(POST: 上電自檢)並將系統控制權交給你指定的下一步驟。BIOS 通常和硬件一同提供。

BIOS 啓動屏幕通常指示了進入 BIOS 配置界面所需的按鍵。流行的按鍵是 F1、F2、F10、Esc、Ins 和 Del 鍵。假如你的啓動屏幕被一個漂亮的圖形界面隱藏,你可以按下某些按鍵(比如 ESC)取消隱藏。這些按鍵高度依賴於硬件。

硬件位置和 BIOS 啓動的代碼的優先級可以在 BIOS 配置界面中選擇。通常,在已選擇的設備(硬盤、軟件、CD-ROM……)中,最先找到的設備的最開始的幾個扇區將被加載到內存,並執行其中的初始化代碼。初始化代碼可以是以下任意一種。

  • 引導加載代碼

  • 類似 FreeDOS 這樣的過濾型操作系統的內核代碼

  • 能夠加載到如此小的空間中的目標操作系統的內核代碼

通常,系統從主硬件的特定分區中引導。傳統 PC 硬盤的最開始兩個扇區中包含了主引導記錄(MBR)。在 MBR 的末尾記錄了磁盤分區信息及引導選擇。BIOS 中執行的首段引導加載代碼佔據了 MBR 的其餘部分。

引導加載程序是啓動過程的第二階段,由 BIOS 啓動。引導加載程序將系統內核映像和 initrd 映像加載到內存並將控制權交給它們。initrd 映像是根文件系統映像,其支持程度依賴於所使用的引導加載程序。

Debian 系統通常使用 Linux 內核作爲其默認的系統內核。當前 2.6/3.x 版本 Linux 內核的 initrd 映像從技術上說是 initramfs(初始化 RAM 文件系統)映像。initramfs 映像是根文件系統中所有文件的 cpio 歸檔再經過 gzip 壓縮得到。

[警告] 警告

使用新的 multi-segment initramfs 之後,上述內容已不正確。請參見錯誤 #790100

Debian 系統默認將 PC 平臺的 GRUB 引導加載程序的第一階段代碼安裝在 MBR 中。可用的引導加載程序和配置選項如下。


[警告] 警告

假如沒有從 grub-rescue-pc 軟件包中的映像製作出來的可引導修覆盤(CD 或軟盤)在手邊,請勿把玩引導加載程序。即使硬盤上沒有可正常工作的引導加載程序,可引導修覆盤也能引導你的系統。

傳統 GRUB 的菜單配置文件位於 /boot/grub/menu.lst。例如,文件中有如下的配置條目。

title           Debian GNU/Linux
root            (hd0,2)
kernel          /vmlinuz root=/dev/hda3 ro
initrd          /initrd.img

GRUB 第 2 版的菜單配置文件位於 /boot/grub/grub.cfg。此文件由 /usr/sbin/update-grub 根據 "/etc/grub.d/*" 中的模板及 "/etc/default/grub" 中的設置自動生成。例如,文件中有如下的配置條目。

menuentry "Debian GNU/Linux" {
        set root=(hd0,3)
        linux /vmlinuz root=/dev/hda3
        initrd /initrd.img
}

這些示例中,GRUB 參數的含義如下。


[注意] 注意

傳統 GRUB 使用的分區號爲 Linux 內核及各種實用工具使用的分區號減 1。GRUB 第 2 版修復了這個問題。

[提示] 提示

在標識一個塊設備時,可能需要使用 UUID(參見第 9.5.3 节 “使用 UUID 訪問分割槽”)而不是類似 "/dev/hda3" 這樣的文件名,例如 "root=UUID=81b289d5-4341-4003-9602-e254a17ac232 ro"。

[提示] 提示

如果使用了 GRUB,內核的啓動參數可以在 /boot/grub/grub.cfg 裏面設置。在 Debian 系統裏,你不應該直接編輯 /boot/grub/grub.cfg。你可以通過編輯 /etc/default/grub 文件中 GRUB_CMDLINE_LINUX_DEFAULT 的值並運行 update-grub(8) 來更新 /boot/grub/grub.cfg

[提示] 提示

通過使用鏈式引導技術,你可以在一個引導裝載程序中啓動另一個引導裝載程序。

參見 “info grub” 及 grub-install(8)

常規 Debian 系統是啓動流程的第四階段,由迷你 Debian 系統啓動。迷你 Debian 系統的內核在此環境下繼續運行。根文件系統將由內存切換到實際的硬盤文件系統上。

init 程序是系統執行的第一個程序(PID=1),它啓動其它各種程序以完成主引導流程。init 程序的默認路徑是 ”/sbin/init“,但可通過內核啓動參數修改,例如 ”init=/path/to/init_program"。

默認的 init 程序一直在變化中:

  • squeeze 之前的 Debian,使用簡單的 SysV 風格的 init。

  • wheezy 版本的 Debian 對 SysV 風格的 init 做了改進:使用 LSB 頭將啓動步驟排序,同時並行執行啓動腳本。

  • jessie版本的 Debian 將默認 init 切換成 systemd,以使用事件驅動和並行初始化。

[提示] 提示

"/etc/init.d/rc"、“/etc/init.d/rcS"、“/usr/sbin/update-rc.d” 及 “/usr/sbin/invoke-rc.d” 腳本中的啓動機制都是相互兼容的。

[提示] 提示

你的系統中實際使用的 init 命令可以使用 “ps --pid 1 -f” 命令確認。


[提示] 提示

有關啟動流程加速的最新資訊,請參見 Debian 維基:啟動流程加速詞條。

[小心] 小心

當前預設的 Debian 系統已不使用 SysV 風格的 init。請閱讀其它資源以獲取關於現代的基於 systemd 的 init。參見 Debian 管理員手冊

本章節描述優秀而老式的 SysV 風格的 init 是如何引導系統的。你的 Debian 系統的運作方式並不與此處描述的內容完全相同,但瞭解這些基礎內容頗具教育意義,因為更新的 init 系統傾向於提供相同的功能。

SysV 風格的啟動流程本質上經歷了以下幾個階段。

  1. Debian 系統進入執行級別 N(無)並根據 “/etc/inittab” 的描述初始化系統。

  2. Debian 系統進入執行級別 S 並在單使用者模式下完成系統的硬體初始化等等。

  3. Debian 系統進入某個指定的多使用者執行級別(2 到 5)並啟動各個系統服務。

多使用者模式的初始執行級別,可通過核心啟動引數 “init=” 指定,或在 “/etc/inittab” 中的 "initdefault" 行指定。已安裝的 Debian 系統以執行級別 2 啟動。

init 系統實際執行的所有指令碼檔案都在 “/etc/init.d/” 目錄中。

參見 init(8)inittab(5) 及 “/usr/share/doc/sysv-rc/README.runlevels.gz” 以獲取確切的解釋。

例如,讓我們來建立如下類似 Red Hat Linux 的執行級別系統。

  • init 預設以 runlevel=3 啟動系統。

  • init 不會在 runlevel=(0,1,2,6) 時啟動 gdm3(1)

  • init 會在 runlevel=(3,4,5) 時啟動 gdm3(1)

可以通過修改 "/etc/inittab" 檔案來改變啟動等級並且也可以使用使用者友好的執行級別管理工具例如 sysv-rc-conf 或者 bum 來更改執行級別。如果你只想用命令列方式的話,如下是你應該怎樣去做的步驟(預設安裝 gdm 軟體包後,在顯示器管理工具中選中它)。

# cd /etc/rc2.d; mv S21gdm3 K21gdm3
# cd /etc; perl -i -p -e 's/^id:.:/id:3:/' inittab

請注意當啟動顯示器管理程序時:xdm,gdm3,sddmwdm,"/etc/X11/default-display-manager" 檔案會被檢查。

[注意] 注意

你也可以在任何控制檯介面用 startx(1) 命令啟動 X。

"/etc/init.d" 中的每個 init 指令碼的預設引數由 "etc/default" 中的對應檔案給出,此對應檔案包含環境變數分配。這些目錄是 Debian 系統特定的,它們大致相當於 Red Hat Linux 和其他發行版中的 "/etc/sysconfig" 目錄。例如,“/etc/default/cron" 可以控制 "/etc/init.d/cron" 的執行方式。

"/etc/default/rcS"檔案可用於定製啟動時預設的 motd(5), sulogin(8), 等.

如果通過改變這些變數不能達到你所想要的效果,那麼你應該修改 init 指令碼。如下是一些系統管理員可以編輯的配置檔案。

許多網路服務(參考第 6 章 網路應用)在啟動多使用者模式的時候通過 init 指令碼直接作為後臺守護程序啟動,例如 “/etc/rc2.d/S20exim4”(執行級別為2)有一個指向 "/etc/init.d/exim4" 的符號連結。

一些網路服務能夠使用 super-server inetd (或者它的等價物) 啟動。在啟動的時候,inetd 通過連結到 "/etc/init.d/inetd" 的 "/etc/rc2.d/S20inetd" 啟動 (執行等級為 2)。根本上,inetd 允許一個正在執行的守護程序去呼叫其它程序,減輕了系統的負載。

任何時候一個服務請求到達 super-server inetd , 通過在"/etc/protocols"和"/etc/services"裡面查詢資料庫,該請求的協議和服務就會被辨識出來。inetd在"/etc/inetd.conf"資料庫裡查詢一個通用的網際網路服務,或者在"/etc/rpc.conf"裡面找到一個基於開放網路計算遠端過程呼叫(ONC RPC)/Sun RPC 的服務。

有些情況下inetd 並不直接啟動對應的服務,而是以"/etc/inetd.conf"中對應服務作為引數啟動TCP wrapper程式tcpd(8) . 在這種情況下, tcpd會根據"/etc/hosts.deny"和"/etc/hosts.allow"進行額外檢查後,啟動相應的服務程式.

為了系統安全,應該儘可能的關掉網路服務程式。參考第 4.6.4 节 “限制訪問某些服務端的服務”

參考 inetd(8), inetd.conf(5), protocols(5), services(5), tcpd(8), hosts_access(5), host_options(5), rpcinfo(8), portmap(8), 和 "/usr/share/doc/portmap/portmapper.txt.gz"。

Linux 核心 2.6 和更新的核心,udev 系統 提供了自動硬體發現和初始化機制。(參見 udev(7)).在核心發現每個裝置的基礎上,udev 系統使用從 sysfs 檔案系統 (參見 第 1.2.12 节 “procfs 和 sysfs”)的資訊啟動一個使用者程序,使用 modprobe(8) 程式 (參見 第 3.3.1 节 “核心模組初始化”)載入支援它所要求的核心模組, 建立相應的裝置節點。

[提示] 提示

如果由於某些理由,"/lib/modules/<kernel-version>/modules.dep"沒有被 depmod(8) 正常生成,模組可能不會被 udev 系統按期望的方式載入。執行"depmod -a" 來修復它。

裝置節點的名字,可以通過"/etc/udev/rules.d/"裡的 udev 檔案來配置.當前預設的規則傾向建立動態生成的名字,除了光碟機和網路裝置外,會生成非靜態的裝置名。通過新增和光碟機、網路裝置類似的個性化規則,你也可以為 USB 盤之類的其它裝置,生成靜態裝置名。 參見 "Writing udev rules" 或 "/usr/share/doc/udev/writing_udev_rules/index.html".

由於 udev 系統是一個正在變化的事物,我在其它文件進行了詳細描述,在這裡只提供了最少的資訊。

[提示] 提示

"/etc/fstab"裡面的掛載規則,裝置節點不必需是靜態的。你能夠使用 UUID 來掛載裝置,來代替"/dev/sda"之類的裝置名. 參見 第 9.5.3 节 “使用 UUID 訪問分割槽”.

通過 modprobe(8) 程式新增和刪除核心模組,使我們能夠從使用者程序來配置正在執行的 Linux 核心。udev 系統(參見 第 3.3 节 “udev 系統”)自動化它的呼叫來幫助核心模組初始化。

下面的非硬體模組和特殊的硬體驅動模組,需要被預先載入,把它們在"/etc/modules"檔案裡列出 (參見 modules(5)).

modprobe(8) 程式的配置檔案是按 modprobe.conf(5)的說明放在"/etc/modprobes.d/" 目錄下,(如果你想避免自動載入某些核心模組,考慮把它們作為黑名單放在"/etc/modprobes.d/blacklist" 檔案裡.)

"/lib/modules/<version>/modules.dep" 檔案由 depmod(8) 程式生成,它描述了 modprobe(8) 程式使用的模組依賴性.

[注意] 注意

如果你在啟動時出現模組載入問題,或者 modprobe(8)時出現模組載入問題, "depmod -a" 可以通過重構"modules.dep"來解決這些問題。

modinfo(8) 程式顯示 Linux 核心模組資訊。

lsmod(8) 程式以好看的格式展示"/proc/modules"的內容,顯示當前核心載入了哪些模組。

[提示] 提示

你能夠精確識別你係統上的硬體。 參見第 9.4.3 节 “硬體識別”.

[提示] 提示

你可以在啟動時配置硬體來啟用期望的硬體特徵。參見 第 9.4.4 节 “硬體配置”.

[提示] 提示

你可以重新編譯核心來增加你的特殊裝置的支援。參見 第 9.9 节 “核心”.