Rootfs 概述:Linux 系统的"最后一公里",以及为什么内核启动后还需要它¶
为什么要写这篇文章¶
当我们谈论嵌入式 Linux 启动流程时,大家通常会关注 U-Boot、内核、设备树这些"高大上"的组件。但很多人(包括我自己刚开始的时候)往往会忽略一个同样关键的部分——Rootfs。
我第一次接触 Rootfs 的时候,心里充满了疑问:内核不是已经编译好了吗?不是已经能跑起来了吗?为什么还需要一个 Rootfs?它到底放什么东西?为什么网上的教程有的用 BusyBox,有的用 Buildroot,还有的直接上 Debian?这些问题当时困扰了我好几天。
后来我才发现,Rootfs 才是 Linux 系统的"最后一公里"。内核负责驱动硬件、管理进程、调度资源,但用户空间的程序、脚本、配置文件——这些才是我们真正和系统交互的方式。没有 Rootfs,内核就像一辆没有方向盘的车,能跑但不知道往哪跑。
更糟糕的是,网上的 Rootfs 教程要么太简单(只告诉你"复制这些文件进去就行"),要么太复杂(一上来就讲 Buildroot 的 100 个配置选项)。新手很容易迷失在各种方案之间,不知道该选哪一个。
所以这篇文章,我想从最基础的概念讲起:什么是 Rootfs,为什么需要它,有哪些常见的方案,以及为什么我们选择 BusyBox 作为入门方案。当你理解了这些,后面的编译配置就会变得顺理成章。
Rootfs 到底是什么¶
如果你在 Linux 终端输入 ls /,你会看到类似这样的输出:
这些目录(大部分)就构成了 Rootfs。它是 Linux 系统启动后挂载的第一个文件系统,是所有用户空间程序的"根"。
内核和 Rootfs 的关系¶
你可能会有一个疑问:内核启动的时候,Rootfs 还没挂载,那内核是怎么找到并挂载它的呢?
答案就在 U-Boot 的 bootargs 环境变量里。你可能见过类似这样的配置:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.1.100:/path/to/rootfs,tcp,v3 ip=dhcp'
这里的 root=/dev/nfs 就是在告诉内核:你的根文件系统在 NFS 上。内核启动完成后,会根据这个参数去挂载对应的 Rootfs。
所以整个启动链条是这样的:
内核的职责是"把车开到目的地"(挂载 Rootfs),而 Rootfs 的职责是"提供驾驶室和控制装置"(shell、命令、配置、服务)。
为什么不能没有 Rootfs¶
理论上,你可以把所有用户程序都编译进内核(作为 initramfs),但这不是个好主意。原因如下:
- 体积问题:一个完整的 Rootfs 可能有几十 MB 甚至几百 MB,全部塞进内核镜像会让内核变得臃肿不堪。
- 灵活性差:每次修改配置、添加程序都要重新编译内核,开发效率极低。
- 不符合设计原则:内核和用户空间本就应该分离,这是 Linux 设计的基本原则。
所以,即使是最简单的嵌入式系统,也需要一个独立的 Rootfs。
Rootfs 方案大比拼:谁才是你的菜¶
当你决定要制作 Rootfs 时,会发现自己面临着很多选择。让我来帮你分析一下常见方案的优缺点。
BusyBox:瑞士军刀,小巧精悍¶
优点: - 体积小:一个二进制文件包含几百个常用命令,最终产物可能只有 1-2 MB - 编译简单:配置项相对较少,新手容易上手 - 可控性强:你完全知道里面放了什么 - 资源占用低:内存和 CPU 占用都很小
缺点: - 功能有限:很多高级功能需要额外配置 - 软件包少:没有包管理器,添加软件需要手动编译 - 适合场景:资源受限的嵌入式设备、学习理解 Linux 基本原理
Buildroot:全家桶,一站式解决方案¶
优点: - 自动化程度高:自动下载、交叉编译、打包所有依赖 - 软件包丰富:支持 2000+ 软件包,包含常用的工具和库 - 灵活配置:通过 menuconfig 选择需要的组件 - 成熟稳定:广泛用于商业产品
缺点: - 编译时间长:首次编译可能需要几小时(我靠我有的说,之前玩RK家的板子,一次编译我等了10来个小时) - 学习曲线陡峭:配置项繁多,新手容易迷失 - 体积较大:完整编译可能上 GB
适合场景: 需要多种软件包的复杂嵌入式系统
Debian/Raspbian:完整发行版,开箱即用¶
优点: - 软件包最丰富:apt-get install 想装什么装什么 - 文档完善:遇到问题容易找到解决方案 - 开发效率高:不需要自己编译常见软件 - 更新及时:安全补丁和软件更新较快
缺点: - 体积庞大:最小安装也要几百 MB - 资源占用高:后台服务多,不适合资源受限设备 - 启动较慢:systemd 等初始化系统比较"重"
适合场景: 树莓派等资源充足的单板机、快速原型开发
Yocto/OpenEmbedded:企业级定制,专业但复杂¶
优点: - 高度可定制:可以精确控制每一个组件 - 企业级支持:适合大规模生产 - 分层设计:便于维护和复用 - 许可证管理:适合商业产品合规需求
缺点: - 学习曲线极陡峭:文档写得像学术论文 - 编译环境复杂:需要大量依赖和配置 - 编译时间极长:完整编译可能需要一天
适合场景: 大规模商业产品、需要严格定制和许可证管理
为什么选择 BusyBox 作为入门方案¶
看到这里,你可能会问:既然 Buildroot 功能更强大,Debian 更方便,为什么我们还要学 BusyBox 呢?
我的回答是:万丈高楼平地起,先把基础打扎实。
BusyBox 是理解 Linux 系统运作原理的最佳起点。它让你能够:
- 理解 Linux 的基本构成:你会亲手创建每一个目录、编写每一个配置文件,深刻理解它们的作用。
- 掌握交叉编译的基本流程:BusyBox 的编译过程是嵌入式开发的经典案例,学会它,其他软件的编译也就触类旁通。
- 建立问题排查能力:当你从零开始构建系统,遇到问题时你会知道去哪里找线索,而不是只会"重启试试"。
- 为进阶学习铺路:理解了 BusyBox,再学 Buildroot 时你就知道它在做什么,而不再是黑盒操作。
此外,BusyBox 本身也很实用。很多商业产品的 Rootfs 就是基于 BusyBox 构建的——它够小、够快、够稳定。(嘿嘿,你猜猜Ubuntu启动失败了进的哪?就是busybox啦)
Rootfs 目录结构速览¶
标准 Linux Rootfs 的目录结构遵循 FHS(Filesystem Hierarchy Standard)规范。让我们快速浏览一下最重要的几个目录:
| 目录 | 作用 | 典型内容 |
|---|---|---|
/bin |
基本用户命令 | ls, cat, cp, mv, sh 等 |
/sbin |
系统管理命令 | ifconfig, reboot, init 等 |
/etc |
配置文件 | inittab, fstab, passwd, init.d/ 等 |
/lib |
共享库 | libc.so, ld-*.so 等 |
/dev |
设备文件 | console, null, tty, mmcblk 等 |
/proc |
虚拟文件系统(进程信息) | /proc/cpuinfo, /proc/meminfo 等 |
/sys |
虚拟文件系统(硬件信息) | /sys/class/, /sys/devices/ 等 |
/tmp |
临时文件 | 运行时生成的临时数据 |
/var |
可变数据 | log, lock, run 等子目录 |
/usr |
用户程序和数据 | /usr/bin, /usr/lib, /usr/share 等 |
/home |
用户主目录 | 普通用户的文件和数据 |
/root |
root 用户主目录 | 管理员的个人文件 |
对于最小化的 BusyBox Rootfs,我们只需要其中的一部分:
- 必需的:/bin、/sbin、/etc、/lib、/dev、/proc、/sys
- 推荐的:/tmp、/usr(至少 /usr/lib)
- 可选的:/home、/var(根据需求)
IMX-Forge 项目的 Rootfs 策略¶
在 IMX-Forge 项目中,我们采用"渐进式"的 Rootfs 构建策略:
- 第一阶段(BusyBox 基础系统):使用 BusyBox 构建最小可启动系统,理解基本原理。
- 第二阶段(目录结构完善):手动创建完整目录结构,添加必要的配置和脚本。
- 第三阶段(网络和存储):添加网络支持、存储挂载等功能。
- 第四阶段(应用程序集成):交叉编译并添加自定义应用程序。
当前项目中的 Rootfs 位于 rootfs/nfs/ 目录,结构如下:
rootfs/nfs/
├── bin/ # BusyBox 及其符号链接
├── etc/ # 配置文件
│ ├── fstab # 文件系统挂载表
│ ├── inittab # init 配置文件
│ └── init.d/ # 启动脚本
│ └── rcS # 系统初始化脚本
├── lib/ # 共享库
├── usr/
│ └── lib/ # 额外的库文件
└── home/ # 用户程序(如 hello 示例)
这个结构虽然是精简的,但已经包含了 Linux 系统最核心的部分,足以支持基本的开发和调试。
写在最后¶
Rootfs 是嵌入式 Linux 系统不可或缺的一部分,但往往被初学者忽视。通过这篇文章,我希望你能够理解:
- Rootfs 是什么,为什么需要它
- 内核和 Rootfs 是如何协作的
- 各种 Rootfs 方案的优缺点
- 为什么 BusyBox 是学习的最佳起点
在下一篇文章中,我们将动手编译 BusyBox。你会看到: - BusyBox 的"瑞士军刀"设计是怎样的 - 如何配置和交叉编译 BusyBox - ARM 架构有哪些特殊注意事项 - 如何将编译好的 BusyBox 安装到 Rootfs
准备好了吗?我们开始动手吧!
下一章:BusyBox 编译安装