3、构建最小根文件系统:选择Target包、配置Busybox、配置glibc/uclibc、首次编译与烧录验证
好,到了真正动手的环节了。前面我们把Buildroot环境搭好,也理解了它的目录结构。现在我们要做的,就是亲手构建一个最小根文件系统。
什么叫最小?说白了,就是能启动、能跑shell、能执行基本命令。没有图形界面,没有桌面环境,甚至连网络服务都可以先不装。我刚开始做嵌入式的时候,总觉得东西越多越安全,结果编译一次半小时,调试起来还互相冲突。后来学乖了——从最小系统开始,逐步往上加,这才是靠谱的做法。
核心原则: 最小根文件系统 = Bootloader + Kernel + 根文件系统(Busybox + C库 + 必要的设备节点)。其他一切,按需添加。
3.1 选择Target包:从零开始
进入Buildroot配置界面:
make menuconfig
你会看到一个层级菜单。别慌,我们一步步来。
3.1.1 Target options
这里选你的目标架构。我以常见的ARM Cortex-A7为例:
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| Target Architecture | ARM (little endian) | 小端模式,大部分ARM芯片都用这个 |
| Target Architecture Variant | cortex-a7 | 根据你的CPU型号选,别选错 |
| Target ABI | EABIhf | 硬浮点,性能更好。如果你的CPU不支持,选EABI |
| Floating point strategy | VFPv4-D16 | 跟CPU的FPU匹配 |
我曾经踩过的坑: 有一次我选了cortex-a7,但实际芯片是cortex-a5。编译出来的内核能启动,但一跑浮点运算就崩。查了两天才发现是Target Architecture Variant选错了。所以,一定要确认你的芯片手册,别想当然。
3.1.2 Build options
这里我建议保持默认。唯一要注意的是:
- Download dir:默认是
dl/,如果你有代理或离线包,可以改 - Number of jobs:填你CPU核心数的1.5倍左右,比如4核填6,编译会快很多
3.1.3 Toolchain
这是关键。Buildroot支持两种方式:
- Buildroot toolchain:自己编译整个工具链,灵活但慢
- External toolchain:用现成的,比如Linaro、ARM官方工具链
我个人习惯用Buildroot自带的,因为版本匹配,省心。但如果你项目急,用外部工具链也行。
Toolchain type: Buildroot toolchain
C library: glibc (或者 uclibc,后面会讲)
Kernel Headers: 和你的内核版本一致
3.2 配置Busybox:麻雀虽小,五脏俱全
Busybox是根文件系统的灵魂。它把几百个Linux命令打包成一个二进制文件,通过符号链接来区分不同命令。
进入Busybox配置:
make busybox-menuconfig
这里我只说几个必须注意的点:
3.2.1 核心配置
| 配置项 | 建议 | 原因 |
|---|---|---|
| Busybox Settings → Build static binary (no shared libs) | 不选 | 动态链接可以减小体积,而且方便后续加库 |
| Busybox Settings → vi-style line editing commands | 选上 | 命令行编辑方便很多 |
| Coreutils → cat, ls, cp, mv, rm, mkdir | 全选 | 这些是基础中的基础 |
| Shells → ash | 选上 | 默认shell,够用 |
| Init utilities → init | 选上 | 系统启动的第一个进程 |
小技巧: 第一次编译,我建议把 Linux System Utilities → mount 和 Linux System Utilities → umount 选上。没有它们,你连文件系统都挂载不了,系统启动到一半就卡住了。
3.2.2 我个人的必选清单
除了上面那些,我还会加这几个:
- find:调试时找文件用
- grep:看日志必备
- sed:脚本里改配置用
- ifconfig:网络调试用
- ping:网络通不通,一ping便知
嗯,其实这些都可以后续再加。但第一次编译,我建议你宁多勿少,省得后面缺命令还要重新编译。
3.3 配置C库:glibc vs uclibc
C库是根文件系统的基石。Buildroot支持多种C库,最常用的是glibc和uclibc。
| 特性 | glibc | uclibc |
|---|---|---|
| 体积 | 大(约1.5MB) | 小(约300KB) |
| 兼容性 | 最好,几乎支持所有POSIX标准 | 大部分兼容,但有些高级功能缺失 |
| 性能 | 优化好,但启动稍慢 | 轻量,启动快 |
| 调试 | 支持完善,gdb等工具友好 | 调试支持较弱 |
| 适用场景 | 功能复杂、需要完整POSIX支持的系统 | 资源受限、对体积敏感的嵌入式设备 |
怎么选?我的经验是:
- 如果你用的是Cortex-A系列,内存128MB以上:用glibc,省心
- 如果是Cortex-M或者内存只有32MB:用uclibc,能省不少空间
- 如果你不确定:先用glibc,后面再换也来得及
我个人的建议: 第一次做项目,用glibc。等你把整个流程跑通了,再考虑换成uclibc来优化体积。别一开始就给自己找麻烦。
3.4 首次编译:耐心等待
配置都做好了,开始编译:
make
第一次编译会下载源码包,然后编译工具链、内核、Busybox、C库……整个过程大概20分钟到1小时,取决于你的网络和机器性能。
编译过程中,你可以去喝杯咖啡。但别忘了盯着终端,万一报错呢?
常见错误:
- 下载失败:检查网络,或者手动把源码包放到
dl/目录下 - 缺少依赖:比如没装
flex、bison,用apt或yum装上就行 - 磁盘空间不足:Buildroot编译会占用不少空间,确保有5GB以上空闲
编译成功后,你会看到:
output/images/
├── rootfs.tar
├── rootfs.cpio
├── zImage
└── ...
rootfs.tar 就是我们的根文件系统。把它解压到目标板的分区上,就能用了。
3.5 烧录与验证:第一次启动
烧录方式取决于你的硬件。我以SD卡启动为例:
# 假设SD卡是 /dev/sdb
sudo dd if=output/images/zImage of=/dev/sdb1
sudo tar xf output/images/rootfs.tar -C /mnt/sd_card
sync
插卡,上电,看串口输出:
U-Boot 2023.01
...
Starting kernel ...
...
VFS: Mounted root (ext4 filesystem) on device 179:2.
Freeing unused kernel memory: 1024K
Run /sbin/init as init process
init started: BusyBox v1.36.0
/ # _
看到这个 / # 提示符了吗?恭喜,你的最小根文件系统跑起来了!
验证清单:
- 输入
ls,看看有没有基本命令 - 输入
cat /proc/cpuinfo,确认CPU信息 - 输入
free,看看内存 - 输入
mount,看看文件系统挂载情况
如果一切正常,恭喜你,你已经掌握了嵌入式Linux最核心的一步。后面的事情,都是在这个基础上做加法。