你是否好奇电脑从按下电源键到登录提示符到底经历了什么?本文深度剖析 Linux 启动全过程。
刚上电时,80x86 特性导致 CS=FFFF、IP=0000,CPU 依据此到 FFFF0H 执行指令。该处始终为 JMP 指令跳转到低地址。ROM BIOS 执行自检(内存、键盘等),在 UMB(高位内存块)扫描合法 ROM(如 SCSI 卡 ROM),有则执行后继续。
最后读取硬盘第一个扇区(MBR,512 字节)。MBR 分两部分:前 446 字节 Pre-Boot 区,后 66 字节分区表。Pre-Boot 区检查哪个分区标记为 Active,然后读取该分区的 Boot 扇区。
boot:,继而加载内核。内核加载入内存后,探测外设(串口、并口、软驱、声卡、硬盘、光驱等),挂载根分区,启动 init 进程(PID=1,所有进程祖先)。
系统开始执行 /etc/rc.d/rc.S,大致初始化脚本顺序:
init[1] rc.S begin rc.serial begin/end rc.S end init[1] enter runlevel 5 rc.M begin rc.inet1 begin/end rc.inet2 begin/end rc.font begin/end rc.local begin/end rc.M end login
rc.S 中先执行 rc.serial,再执行 rc.M,rc.M 包含 rc.inet1/2、rc.font、rc.local,最后 login。
单 # 为原脚本注释,双 ## 为作者注释,无 # 为脚本内容,解释写在内容前。
#!/bin/sh
# /etc/rc
# These commands are executed at boot time by init(8).
# User customization should go in /etc/rc.local.
echo '======== rc.S is running ! System Initializing Now !!! ========'
PATH=/sbin:/usr/sbin:/bin:/usr/bin
# 启动所有 swap
/sbin/swapon -a
# 运行 update 程序:定期将 buffer 数据 sync 写回磁盘,更新 superblock
/sbin/update &
# 检查根分区读写状态
READWRITE=no
if echo -n >> "Testing filesystem status"; then
rm -f "Testing filesystem status"
READWRITE=yes
fi
# 根据读写状态执行不同动作
if [ ! $READWRITE = yes ]; then
/sbin/fsck -A -a
# -A 按 /etc/fstab 检查所有文件系统,-a 自动修复不询问
# fsck 返回值:0 无错,1 已修正,2 需重启,4 未修正,8 操作错,16 语法错,128 共享库错
if [ $? -gt 1 ]; then
echo "fsck returned error code - REBOOT NOW!"
/bin/login
fi
# 正常则以读写重新挂载根设备
echo "Remounting root device with read-write enabled."
/sbin/mount -w -n -o remount /
# -w 读写,-n 不写 /etc/mtab,-o remount 改变读写标志
else
cat << EOF
*** Root partition has already been mounted read-write. Cannot check!
...
(内容未完)