第 3 章 系統初始化

目录

3.1. 啓動過程概述
3.1.1. 第一階段:BIOS
3.1.2. 第二階段:引載加載程序
3.1.3. 第三階段:迷你 Debian 系統
3.1.4. 第四階段:常規 Debian 系統
3.2. SysV-style init
3.2.1. The meaning of the runlevel
3.2.2. The configuration of the runlevel
3.2.3. The runlevel management example
3.2.4. The default parameter for each init script
3.2.5. The hostname
3.2.6. The filesystem
3.2.7. Network interface initialization
3.2.8. Network service initialization
3.2.9. The system message
3.2.10. The kernel message
3.3. The udev system
3.3.1. The kernel module initialization

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

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

[警告] 警告

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

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

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

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

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

[注意] 注意

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

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 节 “Accessing partition using 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” 命令確認。


[提示] 提示

See Debian wiki: BootProcessSpeedup for the latest tips to speed up the boot process.

[小心] 小心

The current default Debian system doesn't use SysV-style init. Please read other resources for the modern systemd based init. See The Debian Administrator's Handbook

This section describes how the good old SysV-style init used to boot the system. Your Debian system does not function exactly as described here but it is quite educational to know this basics since the newer init system tends to offer equivalent functionalities.

The SysV-style boot process essentially goes through the following.

  1. The Debian system goes into runlevel N (none) to initialize the system by following the "/etc/inittab" description.

  2. The Debian system goes into runlevel S to initialize the system under the single-user mode to complete hardware initialization etc.

  3. The Debian system goes into one of the specified multi-user runlevels (2 to 5) to start the system services.

The initial runlevel used for multi-user mode is specified with the "init=" kernel boot parameter or in the "initdefault" line of the "/etc/inittab". The Debian system as installed starts at the runlevel 2.

All actual script files executed by the init system are located in the directory "/etc/init.d/".

See init(8), inittab(5), and "/usr/share/doc/sysv-rc/README.runlevels.gz" for the exact explanation.

For example, let's set up runlevel system somewhat like Red Hat Linux as the following.

  • init starts the system in runlevel=3 as the default.

  • init does not start gdm3(1) in runlevel=(0,1,2,6).

  • init starts gdm3(1) in runlevel=(3,4,5).

This can be done by using editor on the "/etc/inittab" file to change starting runlevel and using user friendly runlevel management tools such as sysv-rc-conf or bum to edit the runlevel. If you are to use command line only instead, here is how you do it (after the default installation of the gdm3 package and selecting it to be the choice of display manager).

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

Please note the "/etc/X11/default-display-manager" file is checked when starting the display manager daemons: xdm, gdm3, sddm, and wdm.

[注意] 注意

You can still start X from any console shell with the startx(1) command.

The default parameter for each init script in "/etc/init.d/" is given by the corresponding file in "/etc/default/" which contains environment variable assignments only. This choice of directory name is specific to the Debian system. It is roughly the equivalent of the "/etc/sysconfig" directory found in Red Hat Linux and other distributions. For example, "/etc/default/cron" can be used to control how "/etc/init.d/cron" works.

The "/etc/default/rcS" file can be used to customize boot-time defaults for motd(5), sulogin(8), etc.

If you cannot get the behavior you want by changing such variables then you may modify the init scripts themselves. These are configuration files editable by system administrators.

Many network services (see 第 6 章 Network applications) are started under multi-user mode directly as daemon processes at boot time by the init script, e.g., "/etc/rc2.d/S20exim4" (for RUNLEVEL=2) which is a symlink to "/etc/init.d/exim4".

Some network services can be started on demand using the super-server inetd (or its equivalents). The inetd is started at boot time by "/etc/rc2.d/S20inetd" (for RUNLEVEL=2) which is a symlink to "/etc/init.d/inetd". Essentially, inetd allows one running daemon to invoke several others, reducing load on the system.

Whenever a request for service arrives at super-server inetd , its protocol and service are identified by looking them up in the databases in "/etc/protocols" and "/etc/services". inetd then looks up a normal Internet service in the "/etc/inetd.conf" database, or a Open Network Computing Remote Procedure Call (ONC RPC)/Sun RPC based service in "/etc/rpc.conf".

Sometimes, inetd does not start the intended server directly but starts the TCP wrapper program, tcpd(8), with the intended server name as its argument in "/etc/inetd.conf". In this case, tcpd runs the appropriate server program after logging the request and doing some additional checks using "/etc/hosts.deny" and "/etc/hosts.allow".

For system security, disable as much network service programs as possible. See 第 4.6.4 节 “Restricting access to some server services”.

See inetd(8), inetd.conf(5), protocols(5), services(5), tcpd(8), hosts_access(5), hosts_options(5), rpcinfo(8), portmap(8), and "/usr/share/doc/portmap/portmapper.txt.gz".

For Linux kernel 2.6 and newer, the udev system provides mechanism for the automatic hardware discovery and initialization (see udev(7)). Upon discovery of each device by the kernel, the udev system starts a user process which uses information from the sysfs filesystem (see 第 1.2.12 节 “procfs 和 sysfs”), loads required kernel modules supporting it using the modprobe(8) program (see 第 3.3.1 节 “The kernel module initialization”), and creates corresponding device nodes.

[提示] 提示

If "/lib/modules/<kernel-version>/modules.dep" was not generated properly by depmod(8) for some reason, modules may not be loaded as expected by the udev system. Execute "depmod -a" to fix it.

The name of device nodes can be configured by udev rule files in "/etc/udev/rules.d/". Current default rules tend to create dynamically generated names resulting non-static device names except for cd and network devices. By adding your custom rules similar to what cd and network devices do, you can generate static device names for other devices such as USB memory sticks, too. See "Writing udev rules" or "/usr/share/doc/udev/writing_udev_rules/index.html".

Since the udev system is somewhat a moving target, I leave details to other documentations and describe the minimum information here.

[提示] 提示

For mounting rules in "/etc/fstab", device nodes do not need to be static ones. You can use UUID to mount devices instead of device names such as "/dev/sda". See 第 9.5.3 节 “Accessing partition using UUID”.

The modprobe(8) program enables us to configure running Linux kernel from user process by adding and removing kernel modules. The udev system (see 第 3.3 节 “The udev system”) automates its invocation to help the kernel module initialization.

There are non-hardware modules and special hardware driver modules as the following which need to be pre-loaded by listing them in the "/etc/modules" file (see modules(5)).

The configuration files for the modprobe(8) program are located under the "/etc/modprobes.d/" directory as explained in modprobe.conf(5). (If you want to avoid some kernel modules to be auto-loaded, consider to blacklist them in the "/etc/modprobes.d/blacklist" file.)

The "/lib/modules/<version>/modules.dep" file generated by the depmod(8) program describes module dependencies used by the modprobe(8) program.

[注意] 注意

If you experience module loading issues with boot time module loading or with modprobe(8), "depmod -a" may resolve these issues by reconstructing "modules.dep".

The modinfo(8) program shows information about a Linux kernel module.

The lsmod(8) program nicely formats the contents of the "/proc/modules", showing what kernel modules are currently loaded.

[提示] 提示

You can identify exact hardware on your system. See 第 9.4.3 节 “Hardware identification”.

[提示] 提示

You may configure hardware at boot time to activate expected hardware features. See 第 9.4.4 节 “Hardware configuration”.

[提示] 提示

You can probably add support for your special device by recompiling the kernel. See 第 9.9 节 “The kernel”.