Kernel / DTB / bootargs / initrd / rootfs 快速理解

可以把 Linux 启动理解成:内核要跑起来,必须知道三件事:我是谁、我在哪、我要去哪里。

  • 我是谁:板子上有哪些硬件?—— 由 DTB 告诉内核。
  • 我在哪:根文件系统在哪个分区、用什么参数启动?—— 由 bootargs 告诉内核。
  • 我要去哪里:最终进入哪个用户空间?—— 由 rootfs 提供。

如果内核还不认识硬盘、分区或文件系统,就需要 initrd/initramfs 先搭一座桥。


五个概念一句话理解

概念 像什么 它做什么
Kernel 操作系统的大脑 管理 CPU、内存、驱动、文件系统
DTB 硬件说明书 告诉内核板子上有哪些设备、地址在哪
bootargs 启动指令单 告诉内核根分区在哪、串口用哪个、是否等待设备
initrd/initramfs 临时小系统 内核启动早期先跑它,加载驱动后再切到真正的 rootfs
rootfs 真正的系统盘 提供 /bin、/sbin、/etc、/lib、/dev 和用户程序

它们各自为什么需要?

1. Kernel:负责执行

内核镜像就是 Linux 本体,比如 Image、zImage、uImage。
它负责初始化 CPU、内存、中断、调度器、驱动和文件系统。

但内核本身不知道这块板子具体长什么样,也不知道根文件系统在哪个分区。

2. DTB:描述硬件

DTB 是设备树二进制文件,由 .dts 编译而来。
它告诉内核:

  • CPU 有几个核;
  • 内存多大;
  • UART、I2C、SPI、GPIO 在哪里;
  • eMMC/SD 控制器怎么接;
  • 时钟、电源、中断如何连接。

有了 DTB,同一个内核镜像可以跑在不同板子上,只需要换 DTB。

3. bootargs:告诉内核怎么启动

bootargs 是 U-Boot 传给内核的一串命令行参数。
常见写法:

console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait rw

含义是:

  • console=ttyS0,115200:日志和终端走串口 0,波特率 115200;
  • root=/dev/mmcblk0p2:根文件系统在 eMMC/SD 的第 2 个分区;
  • rootwait:等设备准备好再挂载根分区;
  • rw:以读写方式挂载。

bootargs 错了,内核可能找不到根分区,就会报:

VFS: Cannot open root device

4. initrd / initramfs:启动早期的临时根文件系统

initrd 和 initramfs 常被混着说,严格来说:

  • initrd:老式机制,是一个块设备格式的内存盘镜像;
  • initramfs:新式机制,是 cpio 归档,内核启动时解压到内存中。

现在大多数发行版默认用的是 initramfs,只是文件名仍常叫 initrd.img。

它的作用是:在内核还无法直接访问真正的根文件系统时,先提供一个临时环境。

临时环境里会做这些事:

  • 加载存储控制器驱动;
  • 加载文件系统模块;
  • 等待 eMMC/SD/NVMe/SATA 等设备就绪;
  • 解密磁盘;
  • 激活 LVM/RAID;
  • 找到真正的 root 分区;
  • 切换过去,执行真正的 /sbin/init。

5. rootfs:系统真正的家

rootfs 是根文件系统,提供:

  • /bin、/sbin:命令;
  • /lib:库文件;
  • /etc:配置;
  • /dev:设备节点;
  • /proc、/sys:内核信息;
  • /usr、/var、/home:应用和数据。

内核挂载 rootfs 后,会启动第一个用户进程,通常是 init 或 systemd,系统才算真正进入用户空间。


为什么 Debian / Ubuntu 需要 initrd?

Debian、Ubuntu 这类通用发行版要跑在很多不同硬件上,所以不能把所有驱动都编译进内核。否则内核会非常大,而且每次换硬件都要重新编译。

它们的典型做法是:

  1. 内核只内置最基础的驱动;
  2. 启动时先加载 initramfs;
  3. initramfs 里探测硬件、加载需要的内核模块;
  4. 找到真正的根分区;
  5. 挂载真正的 rootfs;
  6. 切换到 rootfs,启动 systemd。

比如根分区可能是:

  • /dev/sda2
  • /dev/mmcblk0p2
  • UUID=xxxx-xxxx
  • LVM 卷
  • 加密分区

内核一开始可能并不知道该用哪个驱动访问这些设备,所以需要 initramfs 先帮忙“探路”。


嵌入式板子为什么有时不需要 initrd?

嵌入式系统通常是自己定制的 rootfs,比如用 Buildroot、Yocto 制作。
根文件系统往往直接放在 eMMC/SD 的某个分区,文件系统类型也固定,比如 ext4、squashfs。

如果内核已经把 eMMC/SD 驱动和文件系统驱动编译进去,就可以直接挂载 rootfs,不再需要 initrd。

所以可以这样理解:

  • 嵌入式定制系统:内核知道硬件和分区,通常可以直接挂 rootfs;
  • Debian/Ubuntu 通用发行版:硬件不确定、分区不确定,通常需要 initramfs 过渡。

用一句话串起来

DTB 告诉内核板子上有什么硬件,bootargs 告诉内核根分区在哪里,initramfs 在内核还不认识硬盘时先搭一座桥,rootfs 是系统最终运行的真正根目录,而 Kernel 负责把这些全部组织起来并启动用户空间。