🧩 Linux 内核启动阶段的临时根文件系统技术文档
🧩 Linux 内核启动阶段的临时根文件系统技术文档
📘 1. 概述(Overview)
在 Linux 启动的早期阶段,内核尚未挂载实际的根文件系统(例如 eMMC 上的 ext4 或 NFS 根目录)。
为了让系统具备运行基本命令、加载驱动、挂载真实根文件系统的能力,
内核引入了一种称为 临时根文件系统 (Early Root Filesystem) 的机制。
该机制在不同内核时代有两种主要实现:
阶段 | 技术名称 | 实现方式 |
---|---|---|
Linux 2.4 及以前 | initrd (initial RAM disk) | 将压缩镜像加载为虚拟块设备 /dev/ram0 ,再挂载 |
Linux 2.6 及以后 | initramfs (initial RAM filesystem) | 将 cpio 压缩包直接解包进内存文件系统(ramfs/tmpfs) |
⚙️ 2. 启动阶段流程概览
Linux 启动阶段涉及从 bootloader → 内核 → initramfs/initrd → 用户空间 init 的完整链路。
1. BIOS/UEFI
↓
2. Bootloader (GRUB/U-Boot)
- 加载 vmlinuz (内核映像)
- 加载 initramfs/initrd 到内存
↓
3. Linux Kernel
- 初始化内核子系统
- 创建 rootfs (ramfs/tmpfs)
- 解包 initramfs 或挂载 initrd
- 执行临时根中的 /init
↓
4. /init
- 探测真实根文件系统(eMMC/NFS/overlay)
- 挂载目标根目录
- 调用 `switch_root` 或 `pivot_root`
↓
5. 启动真正的 /sbin/init 或 systemd
🧩 3. 技术架构与数据流
3.1 逻辑结构图
┌────────────────────────────┐
│ Bootloader │
│ - 加载 Kernel + Initramfs │
└────────────┬───────────────┘
│
┌────────────▼───────────────┐
│ Linux Kernel │
│ - 创建 rootfs (ramfs) │
│ - 解包 initramfs.cpio.gz │
│ - 执行 /init │
└────────────┬───────────────┘
│
┌────────────▼───────────────┐
│ /init 用户态脚本 │
│ - 探测真实根文件系统 │
│ - 挂载 /new_root │
│ - switch_root /new_root │
└────────────┬───────────────┘
│
┌────────────▼───────────────┐
│ 真正根文件系统 (ext4/NFS) │
│ /sbin/init → systemd/init │
└────────────────────────────┘
🧱 4. Initramfs 内部结构
Initramfs 是一个 cpio 格式的压缩包,包含早期启动所需的最小文件集:
initramfs/
├── bin/
│ └── busybox
├── dev/
├── etc/
├── proc/
├── sys/
├── init ← 启动脚本(最关键)
└── lib/
典型创建命令:
find . | cpio -H newc -o | gzip > ../initramfs.cpio.gz
加载方式(由 Bootloader 指定):
qemu-system-x86_64 -kernel bzImage -initrd initramfs.cpio.gz -append "console=ttyS0"
🧩 5. 内核解包与挂载流程(源码级)
以 Linux 6.x 为例,主流程如下:
5.1 调用链概览
start_kernel()
└── rest_init()
└── kernel_init()
└── prepare_namespace()
├── create_rootfs()
├── unpack_to_rootfs() ← 解包 initramfs.cpio
└── run_init_process("/init")
5.2 关键函数说明
函数 | 文件 | 功能描述 |
---|---|---|
populate_rootfs() |
init/initramfs.c |
将 cpio 包内容解包到内存文件系统 |
do_mounts_initrd() |
init/do_mounts_initrd.c |
若为旧版 initrd,挂载 /dev/ram0 |
run_init_process() |
init/main.c |
尝试执行 /init 、/sbin/init 等 |
switch_root() |
/usr/sbin/switch_root.c |
从 initramfs 切换到真正 rootfs |
🧩 6. 关键内核配置项
配置项 | 作用 | 典型值 |
---|---|---|
CONFIG_BLK_DEV_INITRD |
启用旧版 initrd 支持 | y |
CONFIG_INITRAMFS_SOURCE |
指定内嵌 initramfs 源路径 | "initramfs_list" |
CONFIG_RD_GZIP |
支持 gzip 压缩 | y |
CONFIG_TMPFS |
允许 tmpfs 用作 rootfs | y |
CONFIG_INIT_ENV_ARG_LIMIT |
控制 /init 参数限制 |
默认 32 |
🧩 7. 内核内嵌 Initramfs
可以直接将 initramfs 打包进内核:
make menuconfig
→ General setup → Initramfs source file(s)
或通过环境变量:
make INITRAMFS_SOURCE=../rootfs
生成的内核会在 usr/initramfs_data.c
中嵌入二进制数据:
const char __initramfs_start[];
const char __initramfs_end[];
⚙️ 8. /init 启动脚本职责
/init
是 initramfs 的“入口点”,它在真正的 /sbin/init
启动前执行。
典型实现(BusyBox 风格):
#!/bin/sh
echo "[INITRAMFS] Booting early init system..."
mount -t proc proc /proc
mount -t sysfs sysfs /sys
# 检测真实根分区
mount /dev/mmcblk0p2 /new_root
# 切换根文件系统
exec switch_root /new_root /sbin/init
🔩 9. 与真实根文件系统的切换机制
9.1 pivot_root(旧方式)
- 将新根文件系统切换到
/new_root
- 原根文件系统挂载到
/new_root/initrd
- 已弃用,需手动卸载旧根
9.2 switch_root(现代方式)
- 替换根并清空旧文件系统
- 由 BusyBox 或 util-linux 提供
- 更简洁、安全
switch_root /new_root /sbin/init
🧩 10. 调试与验证
操作目标 | 命令或方法 |
---|---|
查看内核是否加载 initramfs | dmesg |
解包 initramfs 文件 | gzip -dc initramfs.cpio.gz |
在 /init 中打调试日志 | echo "step 1..." > /dev/console |
查看 rootfs 类型 | cat /proc/filesystems |
切换失败原因分析 | 检查 /dev , /proc , /sys 是否挂载 |
🧩 11. 嵌入式系统应用案例
应用场景 | 描述 |
---|---|
单镜像系统 | BusyBox + initramfs 直接作为系统根,无需外部存储 |
固件升级系统 | initramfs 启动后校验、刷写、重启 |
加密文件系统启动 | initramfs 中负责解密根分区后切换根 |
容灾/救援系统 | 提供最小恢复环境 (rescue shell) |
🧩 12. 实验验证(QEMU Demo)
# 构建 busybox
make defconfig
make install
# 构建 initramfs
mkdir -p rootfs/{bin,dev,proc,sys}
cp -a _install/* rootfs/
echo -e '#!/bin/sh\nmount -t proc proc /proc\nmount -t sysfs sysfs /sys\necho "Hello Initramfs"\nexec /bin/sh' > rootfs/init
chmod +x rootfs/init
find . | cpio -H newc -o | gzip > ../initramfs.cpio.gz
# 启动 QEMU
qemu-system-x86_64 -kernel bzImage -initrd initramfs.cpio.gz -append "console=ttyS0"
输出:
[INITRAMFS] Booting...
Hello Initramfs
/ #
🧩 13. 内存占用与性能分析
项目 | initrd | initramfs |
---|---|---|
解包方式 | 解压到块设备 | 直接展开到 tmpfs |
内存占用 | 双倍(块设备+文件系统) | 单份(直接文件缓存) |
启动速度 | 较慢 | 快 30–50% |
占用结构 | 页缓存 + ramdisk | VFS 缓存 |
回收机制 | 手动卸载 | 自动回收 tmpfs 空间 |
🧩 14. 总结
项目 | initrd | initramfs |
---|---|---|
文件格式 | ext2 镜像 | cpio 包 |
是否需块设备 | 是 | 否 |
文件系统类型 | ext2 | tmpfs/ramfs |
兼容性 | 老内核 | 新内核(2.6+) |
性能 | 一般 | 优秀 |
推荐使用 | ❌ | ✅ |
🧩 15. 参考资料
- Linux Kernel Documentation
/usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt
- BusyBox 官方文档: https://busybox.net/
- 内核源码:
init/initramfs.c
,init/main.c
- LWN: “Early userspace in Linux 2.6”
- Yocto Project: initramfs integration guide