萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

BSD 系統初始化核心腳本 /etc/rc.d/rc.sysinit 完整解析:掛載、檢查、硬體初始化與服務奠基

腳本定位:啟動流程的「地基」

/etc/rc.d/rc.sysinit 是 BSD 風格 init 系統中 **init 進程 (PID 1) 執行的第一個用戶空間腳本** (由 /etc/inittab 中 si::sysinit:/etc/rc.d/rc.sysinit 指定)。它在**切換到任何運行級別之前**運行,負責建立系統運行的最基本環境:文件系統可用、硬體可識別、時間同步、日誌就緒。無論進入單用戶 (1) 還是多用戶 (2/3/5),此腳本**必經且僅執行一次**。

完整流程逐段深度解析

1. 根文件系統初始掛載為唯讀

echo "Mounting root device read-only..."
/bin/mount -n -o remount,ro /
  • 核心啟動參數 ro 已將根 fs 以唯讀掛載。此處顯式 remount,ro 確保狀態一致。
  • -n:不更新 /etc/mtab (此時根 fs 唯讀,寫入會失敗)。
  • **目的**:為後續 fsck 提供穩定、未被寫入的文件系統視圖。

2. 啟用交換分區

echo "Initializing swap partitions..."
/sbin/swapon -a
  • 讀取 /etc/fstab 中類型為 swap 的條目並啟用。
  • **必須在 fsck 前**?通常 fsck 不需 swap,但部分嵌入式/小內存系統 fsck 大分區可能需 swap 支持。順序可互換,但慣例 swap 先行。

3. 文件系統一致性檢查 (fsck) — 關鍵安全網

/sbin/fsck -A -a -C
# -A: 檢查 /etc/fstab 中所有 fs_passno > 0 的文件系統 (並行檢查不同磁碟)
# -a: 自動修復 (無需交互確認, 相當於 -y)
# -C: 顯示進度條 (針對 ext2/3/4)

if [ $? -gt 1 ]; then
    # 返回碼 > 1 表示有錯誤已修復但需重啟, 或未修復的嚴重錯誤
    echo "ERROR: Filesystem severely damaged. Manual fsck required."
    PS1="(Repair filesystem)# "
    export PS1
    /sbin/sulogin          # 進入單用戶 Shell 供管理員手動修復
    /bin/umount -a -r      # 只讀重掛載所有
    /sbin/reboot -f        # 強制重啟
fi

返回碼語義:0=無錯誤, 1=已修復錯誤, 2=需重啟, 4=未修復錯誤, 8=操作錯誤, 16=用法錯誤, 32=用戶取消, 128=共享庫錯誤。

4. 根文件系統重掛載為讀寫

echo "Remounting root device read-write..."
/bin/mount -n -v -o remount,rw /
echo "" > /etc/mtab
/bin/mount -f -o remount,rw /
  • 第一次 mount -n -o remount,rw / 真正重掛載。
  • echo "" > /etc/mtab 清空舊 mtab (舊系統用文件記錄掛載點,現代 systemd 用 /proc/self/mountinfo 替代)。
  • mount -f -o remount,rw / 偽裝掛載,**僅更新 /etc/mtab 不實際調用系統調用**,補齊 mtab 記錄。

5. 掛載其他本地文件系統

echo "Mounting other local filesystems..."
/bin/mount -a -v -t nonfs
  • -a:掛載 /etc/fstab 中所有 noauto 未標記的項目。
  • -t nonfs:排除網絡文件系統 (NFS/SMB),因網路尚未配置好。
  • 此時 /home, /var, /opt 等分區可用。

6. 設置主機名與域名

echo "Setting up hostname..."
/bin/hostname `cat /etc/HOSTNAME | cut -d . -f1`
/bin/domainname `cat /etc/HOSTNAME | cut -d . -f2-`
  • 讀取 /etc/HOSTNAME (如 myserver.example.com)。
  • cut -d . -f1 取第一段作主機名 (myserver)。
  • cut -d . -f2- 取剩餘作域名 (example.com)。
  • 現代系統用 hostnamectl set-hostname 持久化,/etc/hostname 存主機名,域名由 DNS/搜索域決定。

7. 初始化隨機數生成器

if [ -f "/etc/random-seed" ]; then
    echo "Initializing random number generator..."
    /bin/cat /etc/random-seed > /dev/urandom
    rm -f /etc/random-seed
fi
  • 讀取上次關機保存的種子 (rc.0 中 dd if=/dev/urandom of=/etc/random-seed) 寫入核心熵池。
  • **關鍵於早期 SSH 金鑰生成、SSL 證書簽名、TCP ISN 生成** 的加密強度。
  • 讀取後刪除,防止重放攻擊 (下次關機會寫入新種子)。

8. 載入鍵盤映射

echo "Loading keymap..."
/usr/bin/loadkeys -d
  • -d 載入默認鍵盤映射 (通常為 defkeymap.map 或 us.map)。
  • 如需特定語言,替換為 loadkeys /usr/share/kbd/keymaps/.../uk.map.gz。

9. 從硬體時鐘 (RTC) 同步系統時間

echo "Setting system time from hardware clock..."
/sbin/hwclock --hctosys --utc
  • --hctosys:Hardware Clock → System Time。
  • --utc:假設 RTC 存儲 UTC 時間。**關鍵**:雙系統 (Windows/Linux) 環境下,Windows 預設 RTC 為本地時間,Linux 預設 UTC。需統一策略 (建議雙方皆用 UTC,或 Linux 設 --localtime),否則重啟時間漂移。

10. 啟動核心日誌服務

echo "Starting system and kernel log daemons...."
/usr/sbin/syslogd
/usr/sbin/klogd -c3
  • syslogd:用戶空間日誌守護進程,接收應用/系統日誌,按 /etc/syslog.conf 寫入文件。
  • klogd -c3:核心日誌守護進程,從 /proc/kmsg 讀取核心環形緩衝區日誌轉發給 syslogd。-c3 設定控制台日誌級別 (KERN_INFO=3,僅錯誤/警告輸出到控制台)。
  • 現代系統由 systemd-journald 統一接管,rsyslog/syslog-ng 作為後端轉發。

11. 載入核心模組 (可選,被註釋)

# echo "Updating module dependencies..."
# /sbin/depmod -a
  • depmod -a 掃描 /lib/modules/$(uname -r)/ 建立 modules.dep 依賴索引,供 modprobe 使用。
  • 現代發佈版構建 initramfs 時已預執行,開機由 initramfs 載入核心模組 (如磁碟控制器、文件系統驅動) 掛載根 fs,**此處通常無需重複執行**。

Systemd 對應架構對比

rc.sysinit 階段Systemd 對應單元/機制並行化優勢
remount root roinitrd 中完成,switch_root 前-
swapon -aswap.target 引發 systemd-swap.service / fstab generator並行啟動 swap
fsck -Asystemd-fsck@.service (per-fs), fsck.target**不同磁碟並行 fsck**,大幅縮短啟動時間
mount -a nonfslocal-fs.target 依賴 .mount units (fstab generator)並行掛載獨立磁碟分區
hostnamesystemd-hostnamed, hostname.service (設定 /etc/hostname)-
random-seedsystemd-random-seed.service (load/save)-
loadkeyssystemd-vconsole-setup.service (vconsole.conf)-
hwclock --hctosyssystemd-timesyncd / chronyd / ntpd (持續同步,非一次性)持續校準,非僅啟動時
syslogd/klogdsystemd-journald.service (核心), rsyslog.service (兼容)日誌結構化、索引、轉發
depmodinitramfs 打包時預執行,內核模組自動載入 (udev/kmod)-

總結

rc.sysinit 以**線性串行邏輯**完成系統從「核心態」到「用戶態可用」的奠基工作。其核心價值在於:**嚴格的依賴順序 (ro根fs→fsck→rw根fs→本地fs→網路前置條件)、關鍵數據持久化 (隨機種子、硬體時鐘)、故障兜底 (fsck失敗進單用戶修復)**。Systemd 保留了這些邏輯依賴,但以**聲明式單元依賴圖**實現**最大化並行**,並引入 **Generator 機制** 自動將 fstab 轉換為 mount/swap/fsck 單元,實現了從「手寫腳本排序」到「自動拓撲構建」的躍遷。

copyright © 萬盛學電腦網 all rights reserved