前两篇我们已经讲了两件事:
• Linux 启动不是一步完成,而是一场分层接力
• 系统起不来时,先判断到底卡在哪一层
但在真正做启动分析、板级移植、现场排障时,很多人还是会混淆几个角色:
• BootROM 到底是不是 Bootloader?
• U-Boot 负责到哪一步为止?
• Kernel 启动了是不是就算“系统起来了”?
• rootfs 到底算内核的一部分,还是用户空间的一部分?
这些概念一旦混在一起,后面看日志、查问题、改配置就会越来越乱。
所以这一篇只做一件事:
把 BootROM、U-Boot、Kernel、rootfs 四个角色的职责边界彻底讲清。
一句话先讲明白
如果只记一句话,可以先记这个:
BootROM 负责“找到入口”,U-Boot 负责“把内核拉起来”,Kernel 负责“把硬件和系统底座跑起来”,rootfs 负责“把用户空间真正建立起来”。
也可以把它们理解成一条接力链:
1. BootROM 先交出第一棒
2. U-Boot 把 Linux 启动材料准备好
3. Kernel 把系统内核世界搭起来
4. rootfs 把用户空间接起来
只要把这 4 个角色想明白,Linux 启动链就不会再乱。
第一层:BootROM 负责“把系统拉出第一步”
BootROM 是什么?
它通常是芯片内部固化的一小段启动代码,出厂时就已经写死在 SoC 里。
它不是你烧进去的,也不是你日常改的源码,而是芯片自己带的第一阶段启动逻辑。
它最核心的职责其实很简单:
• 判断从哪个介质启动
• 到指定介质里找第一阶段镜像
• 把镜像搬到片内 SRAM/OCRAM 或指定位置
• 跳转过去执行
所以 BootROM 解决的是:
“系统第一步从哪迈出去”的问题。
• 它不负责加载 Linux kernel,
• 不负责解析 rootfs,
• 也不负责运行用户程序。
• 它只做一件事:
把第一阶段引导程序拉起来。
这也是为什么如果启动拨码错了、介质里没镜像、镜像头格式不对,你可能连 U-Boot 字样都看不到。
所以 BootROM 的边界很清楚:
• 它是启动起点
• 但它不是完整 bootloader
• 它只负责把第一棒交出去
第二层:U-Boot 负责“把内核启动条件准备好”
很多人最熟悉的就是 U-Boot,因为它是现场调试里最常直接打交道的那一层。
U-Boot 的职责,概括起来就是:
把 Linux 真正启动前需要的一切准备好。
它通常会做这些事:
• 选择启动介质
• 读取 kernel 镜像
• 读取设备树 dtb
• 按需加载 initrd/initramfs
• 组织 bootargs
• 执行 bootm、booti、bootz
• 把控制权交给内核
如果说 BootROM 负责“找到门”,
那 U-Boot 负责的就是:
把行李收好、路线确认好、把 Linux 送上路。
所以 U-Boot 并不负责运行 Linux 用户程序,也不负责真正挂载 rootfs。
它的职责边界到哪里结束?
到 把控制权交给内核 为止。
这也是为什么很多启动问题都卡在 U-Boot 这一层,比如:
• bootcmd 配错
• bootargs 配错
• 镜像地址不对
• bootm/booti/bootz 用错
• dtb 没加载对
• 启动介质选错
本质上都属于:
内核还没真正接棒,U-Boot 没把启动条件准备对。
第三层:Kernel 负责“把系统底座搭起来”
内核一旦接过控制权,整个系统就进入 Linux kernel 阶段了。
很多人容易误以为:
看到内核日志,就等于系统已经起来。
其实不是。
Kernel 真正负责的是:
• 初始化内存管理
• 建立中断体系
• 初始化调度器
• 初始化定时器
• 建立控制台
• 解析设备树
• 初始化各类驱动
• 识别块设备、串口、网络设备等硬件
• 最终去挂载 rootfs
可以理解成:
Kernel 负责把“内核世界”先建立起来。
它让 CPU、内存、驱动、设备、调度这些核心机制开始工作。
但这时系统还不算真正进入“用户可用状态”。
因为内核只是系统底座,真正的应用、命令、服务,还在用户空间里。
所以 Kernel 的职责边界是:
• 它负责把系统核心跑起来
• 并为用户空间准备运行基础
• 但它不是用户空间本身
第四层:rootfs 负责“把用户空间接起来”
这一层是很多人最容易低估的。
很多人以为 Linux 系统 = kernel。
其实不是。
内核只是核心,真正的用户空间内容都在 rootfs 里,比如:
• /sbin/init
• Shell
• 库文件
• 配置文件
• 系统服务
• 应用程序
• 启动脚本
所以 rootfs 的意义不是“补充点文件”,而是:
它决定 Linux 能不能从“内核启动”进入“系统可用”。
如果 rootfs 挂不上,就会出现非常经典的报错:
VFS: Cannot open root deviceWaiting for root deviceKernel panic - not syncing: VFS: Unable to mount root fs
这些问题不表示内核没起来,而是表示:
内核起来了,但没有把用户空间接起来。
再往后一步,内核还会尝试启动第一个用户空间进程,比如:
/sbin/initsystemdbusybox init
只有这一步真正跑起来,系统才算进入可用状态。
所以从职责边界上说:
• Kernel 负责把 rootfs 挂起来
• rootfs 负责把用户空间接起来
• init 负责把整个系统服务真正拉起来
为什么这 4 层特别容易混?
因为它们在日志上看起来像是一条连续过程,
但实际上,职责已经发生了明显切换。
最容易混淆的几个点是:
1. 看到 U-Boot,就以为“系统已经起来一半”
其实只能说明 BootROM 和前一阶段至少没彻底失败。
2. 执行了 bootm/booti,就以为 Linux 启动完成
其实这只是把控制权交给内核。
3. 看到内核日志,就以为 rootfs 没问题
并不一定。很多问题就死在 rootfs 挂载。
4. rootfs 挂上了,就以为系统一定能进 Shell
也不一定。init 失败照样进不去。
所以分工不清,就很容易误判问题归属。
现场最实用的判断方法
以后再分析 Linux 启动问题,可以直接按这套分工去看:
看不到任何输出
先怀疑 BootROM、启动介质、供电、时钟、早期引导。
能看到 U-Boot,但拉不起内核
重点看 U-Boot:镜像、dtb、bootcmd、bootargs、启动命令。
已经有内核日志
说明 U-Boot 这棒大概率交出去了,重点转到 Kernel。
有 VFS 报错
说明 Kernel 已经起来,重点查 rootfs 和 root=。
rootfs 挂上了但系统还不正常
重点查 init、用户空间、脚本和服务。
你会发现,一旦按角色拆分,很多问题立刻就变清楚了。
最后怎么一句话记住这 4 个角色?
BootROM 负责找到入口,U-Boot 负责加载并启动内核,Kernel 负责建立系统核心并挂载 rootfs,rootfs 负责把用户空间真正运行起来。
如果再压缩成一句最容易记的话,就是:
BootROM 找路,U-Boot 装车,Kernel 铺底,rootfs 开门营业。
结尾
Linux 启动链最容易让人混乱的地方,不是步骤太多,而是角色边界没分清。
一旦你把这 4 层分工想明白:
BootROMU-BootKernelrootfs
后面再看启动日志、分析异常、定位问题,就会顺很多。
因为启动链说到底不是一团糊在一起的黑盒,而是一场职责非常明确的接力。
谁负责哪一棒,谁出了问题,就先查谁。