一、课程导论与启动流程全景

1.1 什么是内核配置?

内核配置,说白了就是给Linux内核「选配件」的过程。

我刚开始接触嵌入式Linux时,觉得内核就是个黑盒子。后来自己编译过几次,才明白——内核配置就是决定「我的内核支持什么,不支持什么」。

比如你的板子上有Wi-Fi模块,那就要在配置里把对应的驱动选上。没有触摸屏?那把触摸驱动关掉,省空间、省编译时间。

内核配置的结果,是一个叫 .config 的文件。里面全是这样的内容:

CONFIG_ARM=y
CONFIG_MMC=y
CONFIG_EXT4_FS=y
CONFIG_USB_EHCI_HCD=m

每个选项就是一个开关。y 表示编译进内核,m 表示编译成模块,n 表示不编译。

我的经验:新手最容易犯的错,就是把所有选项都选上。我曾经给一块只有8MB Flash的板子编译内核,全选后内核镜像直接超了10MB……根本烧不进去。所以,配置内核就像收拾行李箱——只带必需品。

1.2 什么是Rootfs?

Rootfs,全称是 Root Filesystem,根文件系统。

内核启动后,需要一套完整的目录结构才能正常工作。/bin、/sbin、/etc、/lib、/usr……这些目录和里面的文件,组成了Rootfs。

没有Rootfs,内核就是个光杆司令。它知道怎么管理硬件,但没法执行用户程序,没法读取配置文件,甚至连个Shell都跑不起来。

Rootfs里通常包含:

  • init程序——用户空间的第一个进程
  • Shell——比如busybox提供的sh
  • 库文件——比如glibc或musl
  • 配置文件——比如inittab、fstab
  • 设备节点——比如/dev/console

一句话总结:内核是骨架,Rootfs是血肉。两者缺一不可。

1.3 为什么需要挂载?

你想想看,内核启动时,Rootfs存在哪里?

可能是Flash分区、SD卡、NFS网络文件系统,甚至是内存中的ramdisk。内核需要把这些存储介质上的文件系统,关联到根目录 / 上——这个过程就叫「挂载」。

挂载的本质,就是建立「存储设备」和「目录树」之间的映射关系。

举个例子:

mount /dev/mmcblk0p2 /mnt/rootfs

这条命令把SD卡的第二个分区挂载到 /mnt/rootfs。但内核启动时,挂载的是根文件系统,所以命令是:

mount -t ext4 /dev/mmcblk0p2 /

嗯,这里要注意——根文件系统的挂载是由内核完成的,不是用户手动执行的。内核在启动参数里指定了 root=/dev/mmcblk0p2,它就会自动去挂载。

我曾经踩过的坑:有一次我改了分区表,忘了更新内核启动参数里的root=。结果内核启动时找不到根文件系统,直接panic了。屏幕上就一行字:VFS: Unable to mount root fs on unknown-block(0,0)。排查了半天才发现是root参数没改。

1.4 从按下电源键到登录Shell的完整旅程

这一节,我们来走一遍完整的启动流程。我把它分成几个阶段:

阶段一:BootROM

按下电源键,CPU复位。芯片内部的BootROM开始执行。它初始化最基本的硬件(时钟、内存控制器),然后去固定的位置找启动代码。

启动介质可能是NAND Flash、eMMC、SD卡,或者SPI Flash。BootROM会按优先级去尝试。

阶段二:Bootloader

BootROM加载的第一段代码,通常是SPL(Secondary Program Loader)或U-Boot SPL。它负责初始化DRAM,然后把完整的Bootloader(比如U-Boot)加载到内存中。

U-Boot启动后,会读取环境变量,加载内核镜像和设备树(DTB)到内存,然后跳转到内核入口。

阶段三:内核解压与初始化

内核镜像通常是压缩过的(zImage或Image.gz)。U-Boot跳转后,内核自解压代码先把自己解压到内存中,然后开始执行。

内核初始化流程大致如下:

  1. 设置页表,开启MMU
  2. 初始化中断控制器
  3. 初始化定时器
  4. 初始化控制台(串口)
  5. 解析设备树,初始化各个驱动
  6. 挂载根文件系统
  7. 执行第一个用户进程——init

阶段四:用户空间初始化

init进程启动后,会读取配置文件(比如 /etc/inittab),启动各种服务:

  • 网络服务(dhcp、sshd)
  • 日志服务(syslogd)
  • 登录服务(getty)

最后,getty在串口或终端上显示登录提示符:

Welcome to Embedded Linux
board login: root
Password: 
# 

到这里,你就看到了Shell提示符。整个启动流程完成。

1.5 启动流程全景图

下面这张SVG图,把整个流程串起来了。我建议你多看几遍,把每个阶段的关键动作记住。

嵌入式Linux启动流程全景图 阶段1: BootROM 初始化时钟、内存 加载SPL/U-Boot SPL 阶段2: Bootloader U-Boot初始化 加载内核+DTB 阶段3: 内核 解压、初始化 挂载Rootfs 阶段4: 用户空间 init启动服务 getty → Shell 内核配置决定 • 支持哪些硬件 • 文件系统类型 • 驱动是y/m/n Rootfs包含 • /bin /sbin /etc • init程序 • 库文件、配置 挂载的本质 存储设备 → 目录树 root=/dev/mmcblk0p2 VFS: Virtual Filesystem 内核配置 + Rootfs + 挂载 = 完整的启动流程

1.6 本章小结

这一章我们聊了三件事:

  • 内核配置——给内核选配件,生成.config文件
  • Rootfs——根文件系统,用户空间的基础
  • 挂载——把存储设备映射到目录树

然后走了一遍完整的启动流程:BootROM → Bootloader → 内核 → 用户空间。

后面的章节,我们会深入每个环节。比如内核配置的具体选项怎么选,Rootfs怎么制作,挂载参数怎么调优。

嗯,先把这张全景图印在脑子里。后面的路就好走了。

一句话记住本章:启动流程就是「硬件初始化 → 加载内核 → 挂载Rootfs → 启动用户程序」这四个步骤的接力赛。

可可精品资料库