1. 课程导入
在嵌入式Linux系统中,内核启动完成后,第一件必须完成的事情就是挂载根文件系统(rootfs)。没有可用的rootfs,内核即使成功启动,也无法进入用户空间,更无法运行应用程序。因此,文件系统是嵌入式Linux产品从“能启动”走向“能工作”的关键一环。本课程以BusyBox为起点,逐步构建一个可启动、可裁剪、可量产的嵌入式Linux根文件系统,帮助学习者建立从工具链到镜像烧录的完整能力。
一、学习目标:从“会编译”到“能交付”
本课程不是单纯讲解某个命令或某个目录,而是围绕一个真实可运行的rootfs展开。学习完成后,应达到以下目标:
- 理解Linux文件系统的层次结构、挂载机制与VFS抽象模型;
- 掌握BusyBox的编译、安装与符号链接机制,能独立生成基础用户空间;
- 能够编写和调试
/etc/inittab、/etc/fstab、/etc/init.d/rcS等启动脚本; - 掌握根文件系统镜像的制作方法,包括ext4、UBIFS、SquashFS、initramfs等常见格式;
- 能够根据产品需求裁剪系统体积、配置设备节点、设置用户权限与只读保护;
- 具备定位“内核已启动但无法进入控制台”“挂载失败”“init进程异常”等问题的排障能力。
核心判断标准:当串口终端出现Please press Enter to activate this console,并且能够执行ls、mount、ifconfig等命令时,说明一个最小可用rootfs已经构建成功。
二、核心概念:rootfs、VFS与挂载
嵌入式Linux文件系统涉及几个必须厘清的概念。首先是rootfs,即根文件系统,它是内核挂载的第一个文件系统,承载/bin、/sbin、/etc、/dev、/proc、/sys等关键目录。其次是VFS(Virtual File System,虚拟文件系统),它为上层应用提供统一的文件操作接口,屏蔽了ext4、YAFFS2、UBIFS、NFS等具体文件系统的差异。最后是挂载,Linux通过mount将存储设备、内存文件系统或网络文件系统关联到目录树中的某个挂载点。
理解这三者关系,才能明白为什么内核启动参数中的root=、rootfstype=、init=如此重要。它们分别告诉内核:根文件系统在哪里、是什么类型、第一个用户空间进程是谁。
三、整体知识框架:四层递进
本课程的知识框架可以概括为四层递进关系。第一层是内核与VFS,理解内核如何识别文件系统类型、如何完成根挂载。第二层是BusyBox与用户空间,掌握如何用一个小型二进制提供上百个常用命令。第三层是目录布局与启动配置,包括/etc下的初始化脚本、设备节点创建、环境变量设置。第四层是镜像制作与量产,将目录树打包为可烧录的镜像文件,并考虑只读、压缩、掉电保护等产品化需求。
| 阶段 | 核心任务 | 关键产物 | 常见工具 |
|---|---|---|---|
| 内核启动 | 挂载rootfs,启动init | 内核日志、启动参数 | bootargs、printk |
| BusyBox构建 | 交叉编译、安装符号链接 | busybox二进制、/bin目录 | make menuconfig、make install |
| 目录与配置 | 编写inittab、fstab、rcS | 可启动的rootfs目录树 | vi、chmod、mknod |
| 镜像制作 | 打包为ext4/UBIFS/SquashFS | rootfs.img、rootfs.ubifs | mkfs.ext4、mkfs.ubifs、mksquashfs |
| 调试与量产 | 启动验证、体积裁剪、只读保护 | 稳定可量产的固件 | 串口终端、df、du、mount |
四、实战路线图:从零到可启动系统
建议按照以下顺序推进实践,每一步都应有明确的验证点:
- 准备交叉工具链:确认
arm-linux-gnueabihf-gcc或对应架构编译器可用,并设置CROSS_COMPILE与ARCH。 - 编译BusyBox:下载源码,执行
make menuconfig,选择静态编译或动态编译,安装到_install目录。 - 搭建目录骨架:创建
bin sbin etc dev proc sys tmp var lib等目录,复制BusyBox产物。 - 编写启动脚本:配置
/etc/inittab,在/etc/init.d/rcS中挂载proc、sysfs、devtmpfs,设置网络与主机名。 - 制作镜像并烧录:使用
mkfs.ext4或mksquashfs生成镜像,通过TF卡、NFS或烧录工具部署到目标板。 - 启动验证与排障:观察串口输出,确认init进程启动、控制台可用、关键服务正常。
# 典型BusyBox安装与rootfs骨架命令
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make -j4
make install
mkdir -p rootfs/{bin,sbin,etc/init.d,dev,proc,sys,tmp,var,lib,usr}
cp -a _install/* rootfs/
mknod rootfs/dev/console c 5 1
mknod rootfs/dev/null c 1 3
学习建议:不要一开始就追求功能完整。先做出一个能进入控制台的最小系统,再逐步添加网络、存储、图形界面等组件。每增加一个功能,都要回到串口终端验证,避免问题堆积。
五、常见误区与复盘
初学者最容易陷入的误区有三个。第一,把文件系统等同于目录树,忽略了挂载点和VFS的抽象作用,导致遇到“目录存在但内容为空”时无法判断是挂载失败还是文件缺失。第二,忽略动态库依赖,BusyBox动态编译后未将libc.so等库复制到/lib,启动时出现not found。第三,设备节点缺失,没有创建/dev/console和/dev/null,导致init无法打开控制台。
排障口诀:先看内核日志,再看挂载点,最后查init脚本。内核日志告诉你rootfs是否挂载成功;mount命令告诉你当前挂载状态;init脚本决定用户空间能否正常启动。
本课程后续将围绕上述路线图逐层展开,每一节都对应一个可操作的实践环节。只要跟随课程完成每个验证点,最终就能独立构建一个体积可控、启动稳定、可量产的嵌入式Linux根文件系统。