在前一篇文章中,我们已经完成了BusyBox的源码修改、配置与编译。然而,仅仅拥有编译产物还不足以支撑一个可用的Linux运行环境。本期,我们将聚焦于根文件系统的功能完善,重点解决动态库依赖与系统目录结构两大核心问题,为后续的系统测试与部署打下坚实基础。
一、为何必须手动添加动态库?
在Linux系统中,绝大多数应用程序(包括我们后续会放入的Java、C++、Python运行时)都依赖于动态链接库(.so文件)来运行。BusyBox本身虽然是一个静态编译的“瑞士军刀”式二进制,但用户自行添加的应用程序几乎都需要动态库支持。
核心原因:交叉编译工具链(如arm-linux-gnueabihf-gcc)在编译时会链接目标板所需的库,但目标板的根文件系统默认是空的,没有任何库文件。因此,我们需要将交叉编译器内置的库文件同步到根文件系统中,否则系统启动后连最基本的shell命令都可能无法执行。
⚠️ 注意事项:初学者往往对库文件感到陌生。本教程采用“全量拷贝”策略,将交叉编译器中的所有库文件复制到根文件系统。虽然这样会使最终镜像体积偏大,但能确保兼容性。有经验的工程师可以基于ldd命令分析,进行精细化裁剪。
二、添加核心库:rootfs/lib 目录
首先,我们需要在rootfs根目录下创建lib文件夹,用于存放系统最基础的C库与动态链接器。创建命令如下:
mkdir lib
接下来,进入交叉编译器的库目录。在我们此前的Ubuntu 20.04环境中,交叉编译器通常安装在/usr/local/arm/路径下。具体库文件路径如下:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
该目录下包含了大量的*.so(动态库)与*.a(静态库)文件。为了方便,我们直接将所有库文件拷贝至rootfs/lib目录,使用以下命令:
cp *so* *.a /home/duan/linux/nfs/rootfs/lib/ -d
⚠️ 注意命令末尾的-d参数,它表示拷贝符号链接本身而非链接指向的文件。这里有一个特例:ld-linux-armhf.so.3(动态链接器/解释器)。该文件是系统启动任何动态链接程序时最先加载的模块,它本身不能是一个符号链接,必须是真实存在的文件。
我们先查看一下它的链接状态,如下图所示:

上图中箭头(->)表明它指向了ld-2.19-2014.08-1-git.so。若保持符号链接状态,目标板上的内核将无法正确解析该文件,导致所有程序启动失败。因此,我们需要将其“打回原形”。
操作步骤:首先删除rootfs/lib下的软链接文件,然后重新复制真实文件。
rm ld-linux-armhf.so.3
cp ld-linux-armhf.so.3 /home/duan/linux/nfs/rootfs/lib/
完成替换后,我们再次查看该文件属性,确认其已变为普通文件,如下图所示:

至此,rootfs/lib目录下的基础库已初步就绪。我们也可以顺便查看一下目录内容,确认拷贝结果无误:

另外,交叉编译器中还有一部分与C++标准库、数学库等相关的额外库文件,存放于另一子目录中,我们也需要一并拷贝:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
cp *so* *.a /home/duan/linux/nfs/rootfs/lib/ -d
完成上述步骤后,rootfs/lib目录的最终状态应如下图所示,包含完整的动态加载器与基础运行库(类似Java虚拟机在桌面端所需的JRE核心库):

三、扩展应用库:rootfs/usr/lib 目录
除了基础/lib目录,许多应用层的库(如libstdc++、zlib等)通常存放在/usr/lib目录下。我们需要在rootfs的usr目录下创建lib子目录,并将交叉编译器对应的应用库拷贝进去。
创建并进入目标目录后,执行以下拷贝命令(同样保留符号链接):
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/
usr/lib
cp *so* *.a /home/duan/linux/nfs/rootfs/usr/lib/ -d
完成拷贝后,rootfs/usr/lib目录下将包含大量开发库文件,这为后续移植如TypeScript编译后的Node.js环境、Python解释器或C++编写的守护进程提供了必要的依赖支持。其目录结构应如下图所示:

✅ 实践建议:如果后续发现某个应用程序提示缺少libxxx.so,可直接在交叉编译器的lib目录下搜索并单独拷贝至对应位置,无需全部重新拷贝。
四、构建系统目录骨架
Linux根文件系统遵循FHS(文件系统层次结构标准)。除了/lib和/usr,我们还需要创建若干关键目录,它们是系统启动和日常运行的基石。
必须创建的目录包括:
- dev:存放设备节点文件(如console、null)。
- proc:挂载proc虚拟文件系统。
- sys:挂载sysfs虚拟文件系统。
- mnt:临时挂载点(如U盘、SD卡)。
- tmp:临时文件存放目录。
- root:root用户的家目录。
执行mkdir命令创建上述文件夹,完成后目录结构应如下图所示:

至此,一个具备基本运行能力的根文件系统已经搭建完毕。它已经能够支持动态链接的C/C++程序运行,也为后续集成高级语言运行时(如Java的JRE或JavaScript的Node.js)预留了标准目录接口。
五、总结与下期预告
本文通过三大步骤完善了BusyBox构建的根文件系统:① 拷贝动态库至/lib与/usr/lib;② 修复关键符号链接文件;③ 创建系统标准目录。这些操作确保了根文件系统具备运行标准Linux程序的能力。
[AFFILIATE_SLOT_1]
在下一期中,我们将把该根文件系统打包并实际烧录到目标板进行启动测试,验证其是否能够正常挂载并运行初始化进程。敬请期待!
核心要点回顾:
- 动态链接器(ld-linux)必须是实体文件。
- 使用
-d保留符号链接可节省空间。 - 系统目录骨架(dev/proc/sys)是内核挂载虚拟文件系统的必需挂载点。
[AFFILIATE_SLOT_2]
浙公网安备 33010602011771号