系列简介:TinyLinux 是由 LabHub 发起的"大道至简"Linux 学习项目。我们通过对内核进行"剔骨"级的物理精简,旨在构建一个 100% 透明、可重现的极简实验室。
公众号:LabHub | 项目仓库:https://gitee.com/lynyujiang/tiny-linux.git
scripts/run_qemu.shoverlay/etc/init.d/rcS | |
console=ttyS0 root=/dev/ram0。决定内核如何初始化硬件和挂载根文件系统。┌─────────────────────────────────────────────────────────────────┐
│ 阶段 1: BIOS/UEFI 初始化 (约 0.05 秒) │
│ - POST (Power-On Self Test) │
│ - 硬件检测和初始化 │
│ - 引导设备选择 │
│ - 加载 Boot Sector │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 阶段 2: 内核解压和早期初始化 (约 0.05 秒) │
│ - bzImage 解压到内存 │
│ - 设置页表和内存管理 │
│ - early_printk 开始输出 │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 阶段 3: 内核核心初始化 (约 0.35 秒) │
│ - CPU 和内存子系统初始化 │
│ - 中断控制器设置 │
│ - 调度器和定时器初始化 │
│ - 设备驱动探测 │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 阶段 4: initramfs 加载 (约 0.20 秒) │
│ - 解压 cpio 归档 │
│ - 挂载为临时根文件系统 │
│ - 准备用户空间环境 │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 阶段 5: init 进程执行 (约 0.70 秒) │
│ - 执行 /sbin/init (PID=1) │
│ - 挂载 /proc /sys /dev │
│ - 运行 /etc/init.d/rcS │
│ - 启动 mdev 设备管理器 │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 阶段 6: Shell 提示符 (约 0.06 秒) │
│ - 显示欢迎信息 │
│ - 加载 /etc/profile │
│ - 显示 TinyLinux# 提示符 │
└─────────────────────────────────────────────────────────────────┘
总启动时间:约 1.41 秒
在虚拟化环境中,串口(ttyS0)是最佳的调试通道:
#!/bin/bash
###############################################################################
# TinyLinux OS - QEMU Execution Script
###############################################################################
export LC_ALL=C LANGUAGE=C LANG=C
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/../env.sh"
# 内核和 initrd 路径
KERNEL_PATH="${TINYLINUX_TARGET_DIR}/bzImage"
INITRD_PATH="${TINYLINUX_TARGET_DIR}/rootfs.cpio.xz"
# QEMU 基础参数
QEMU_ARGS="-m 512 -smp 1" # 512MB 内存,单核
QEMU_ARGS="$QEMU_ARGS -kernel ${KERNEL_PATH}" # 直接内核启动
QEMU_ARGS="$QEMU_ARGS -initrd ${INITRD_PATH}" # 加载 initrd
QEMU_ARGS="$QEMU_ARGS -nographic -no-reboot" # 无图形,崩溃不重启
# 内核启动参数(关键!)
APPEND="console=ttyS0 earlyprintk=serial,ttyS0,115200 root=/dev/ram0 rdinit=/sbin/init loglevel=7 debug panic=1"
echo "Command: qemu-system-x86_64 $QEMU_ARGS -append \"$APPEND\""
echo "TIP: Press 'Ctrl+A then X' to exit QEMU."
qemu-system-x86_64 $QEMU_ARGS -append "$APPEND"
console | ttyS0 | |
earlyprintk | serial,ttyS0,115200 | |
root | /dev/ram0 | |
rdinit | /sbin/init | |
loglevel | 7 | |
debug | ||
panic | 1 |
#!/bin/sh
# TinyLinux Minimal Init
# 1. 基础挂载
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev 2>/dev/null || true
# 2. 设置主机名
# hostname TinyLinux
# 3. 打印精简欢迎语
cat /etc/issue 2>/dev/null
# /etc/profile: Minimal shell setup
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PS1='TinyLinux# '
# 常用别名
alias ll='ls -l'
alias df='df -h'
alias free='free -h'
# 自动打印版本(如果存在)
[ -f /etc/version ] && cat /etc/version
| 总计 | 从开机到 Shell | 1.41s |
[ 0.000000] Linux version 6.12.51 (devhub@devhub)
# 内核版本和编译者
[ 0.000000] Command line: console=ttyS0 earlyprintk=serial,ttyS0,115200...
# 内核命令行参数
[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
# 内存映射:0-640KB 可用
[ 0.017608] RAMDISK: [mem 0x1fee7000-0x1ffdffff]
# initrd 在内存中的位置
[ 0.407530] Unpacking initramfs...
# 开始解压 initramfs
[ 0.566051] Freeing initrd memory: 996K
# initrd 解压完成,释放 996KB
[ 0.671365] Run /sbin/init as init process
# 启动 init 进程(PID=1)
[ 1.410488] TinyLinux#
# Shell 就绪
内存地址范围 用途
0x00000000 - 0x0009fbff 常规内存 (640KB)
0x0009fc00 - 0x0009ffff 保留 (EBDA)
0x000f0000 - 0x000fffff BIOS ROM
0x00100000 - 0x1ffdffff 可用内存 (约 500MB)
0x1fee7000 - 0x1ffdffff initrd 镜像 (996KB)
0x1ffe0000 - 0x1fffffff 保留
1. CPU 和 FPU
2. 内存管理 (MTRR, PAT)
3. 中断控制器 (IOAPIC)
4. 定时器 (TSC, PIT)
5. 串口 (ttyS0) ← 关键!
6. RTC 时钟
7. PCI 总线枚举
8. 块设备 (IDE/ATA)
9. 输入设备 (键盘)
cd /home/devhub/xlabs/tiny-linux
# 启动并保存日志
./scripts/run_qemu.sh 2>&1 | tee boot.log
# 提取关键时间戳
grep -E "^\[\s*[0-9]+\.[0-9]+\]" boot.log | head -20
# 计算 init 启动时间
grep "Run /sbin/init" boot.log
# 输出:[ 0.671365] Run /sbin/init as init process
# 计算 Shell 就绪时间
grep "TinyLinux#" boot.log || grep "console" boot.log | tail -1
# 编辑 run_qemu.sh,修改 loglevel
# 从 loglevel=7 改为 loglevel=4(减少输出)
APPEND="console=ttyS0 ... loglevel=4"
# 重新启动观察差异
./scripts/run_qemu.sh
# 编辑 overlay/etc/init.d/rcS
cat > overlay/etc/init.d/rcS << 'EOF'
#!/bin/sh
# TinyLinux Enhanced Init
echo"Starting TinyLinux..."
echo"Kernel: $(uname -r)"
echo"Boot time: $(date)"
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev 2>/dev/null || true
cat /etc/issue
EOF
# 重新构建
./scripts/make_all.sh
# 终端 1: 启动 QEMU(带 GDB)
qemu-system-x86_64 -m 512 -kernel output/target/bzImage \
-initrd output/target/rootfs.cpio.xz -nographic -s -S
# 终端 2: 连接 GDB
gdb vmlinux
(gdb) target remote :1234
(gdb) break start_kernel
(gdb) continue
启动过程中重点关注:
1. BIOS 阶段(约 0.05s)
SeaBIOS (version 1.16.3-debian-1.16.3-2)
Booting from ROM...
2. 内核版本信息
[ 0.000000] Linux version 6.12.51 (devhub@devhub) ...
3. 命令行参数
[ 0.000000] Command line: console=ttyS0 earlyprintk=serial,ttyS0,115200...
4. 内存映射
[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
5. initramfs 加载
[ 0.407530] Unpacking initramfs...
[ 0.566051] Freeing initrd memory: 996K
6. init 进程启动
[ 0.671365] Run /sbin/init as init process
7. Shell 就绪
TinyLinux#
console=ttyS0 | ||
rdinit=/sbin/init | ||
-nographic | ||
./scripts/run_qemu.sh
SeaBIOS (version 1.16.3-debian-1.16.3-2)
Booting from ROM...
[ 0.000000] Linux version 6.12.51 (devhub@devhub) (gcc ... 14.2.0) #1 Sun Mar 8 12:51:17 CST 2026
[ 0.000000] Command line: console=ttyS0 earlyprintk=serial,ttyS0,115200 root=/dev/ram0 rdinit=/sbin/init loglevel=7 debug panic=1
[ 0.000000] BIOS-provided physical RAM map:
[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000001ffdffff] usable
[ 0.017608] RAMDISK: [mem 0x1fee7000-0x1ffdffff]
[ 0.407530] Unpacking initramfs...
[ 0.566051] Freeing initrd memory: 996K
[ 0.671365] Run /sbin/init as init process
[ 0.674819] with arguments:
[ 0.674851] /sbin/init
[ 0.674873] with environment:
[ 0.674895] HOME=/
[ 0.674917] TERM=linux
Please press Enter to activate this console.
TinyLinux#
# 1. 查看内核版本
uname -a
# 输出:Linux TinyLinux 6.12.51 #1 Sun Mar 8 12:51:17 CST 2026 x86_64 GNU/Linux
# 2. 查看启动时间
dmesg | head -5
# 输出:[ 0.000000] Linux version...
# 3. 查看进程
ps
# 输出:PID 1 (init), PID 50 (shell)
# 4. 查看内存
free -h
# 输出:约 498MB 可用
# 5. 查看挂载点
mount
# 输出:proc, sysfs, devtmpfs
9e35606c4 | |
git checkout 9e35606c4 | |
source env.sh && ./scripts/run_qemu.sh | |
TinyLinux# |
⚠️ 注意:Git 提交信息请执行
git log --oneline -5获取最新提交。
通过本章,我们掌握了系统启动流程的核心知识:
| 总计 | 1.41s | 从开机到 Shell |
在 [TinyLinux-010] 中,我们将探索系统调试技巧,包括 GDB 调试、内核转储和性能分析。敬请期待!
如果你觉得这个项目对理解 Linux 底层有帮助,请不要吝啬你的支持:
本文由 LabHub 团队原创,转载请注明出处。
项目地址:https://gitee.com/lynyujiang/tiny-linux.git