1. 前言:为什么需要完善根文件系统?
在上一期的工作中,我们已经完成了BusyBox的编译和基础配置。但一个完整的Linux根文件系统远不止BusyBox这么简单。就像盖房子一样,BusyBox只是提供了基础的"建筑材料",我们还需要添加各种"配套设施"才能让系统真正运转起来。
做过嵌入式开发的朋友都知道,根文件系统是Linux系统启动后挂载的第一个文件系统。它包含了系统运行所需的所有关键组件:二进制程序、库文件、配置文件、设备节点等等。一个不完整的根文件系统会导致各种奇怪的问题——程序无法运行、命令报错、甚至系统无法启动。
2. 向根文件系统添加lib库
2.1 理解Linux动态链接库
在开始操作之前,有必要先了解下Linux的库文件机制。Linux下的程序通常分为静态编译和动态编译两种:
- 静态编译:所有依赖都打包进可执行文件,体积大但部署简单
- 动态编译:运行时才加载共享库,体积小但需要配套的库文件
BusyBox默认采用动态编译,因此我们需要准备相应的动态链接库(.so文件)。这些库文件就像Windows下的DLL,为应用程序提供基础功能支持。
2.2 定位交叉编译器的库文件
我们的目标平台是ARM架构,因此需要使用交叉编译器配套的ARM版本库文件。以文中使用的gcc-linaro-4.9.4为例,库文件主要存放在两个位置:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
注意:不同版本的交叉编译器路径可能略有不同,建议先用
find命令定位.so文件所在目录
2.3 拷贝库文件到根文件系统
2.3.1 创建lib目录
首先在根文件系统中创建存放库文件的目录:
bash复制mkdir -p /home/duan/linux/nfs/rootfs/lib
mkdir -p /home/duan/linux/nfs/rootfs/usr/lib
2.3.2 拷贝基础库文件
进入交叉编译器的libc/lib目录,拷贝所有.so和.a文件:
bash复制cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
cp *so* *.a /home/duan/linux/nfs/rootfs/lib/ -d
这里有几个关键点需要注意:
-d参数:保留符号链接关系,避免库文件冗余*so*通配符:匹配所有.so和.version.so等变体.a文件:静态库,虽然BusyBox是动态编译,但保留静态库以备不时之需
2.3.3 处理特殊的ld-linux库
ld-linux-armhf.so.3是一个特殊的库文件,它实际上是动态链接器本身。如果保留为符号链接,在目标系统上可能会因为路径问题导致程序无法运行。
解决方法:
bash复制# 先删除原有的符号链接
rm /home/duan/linux/nfs/rootfs/lib/ld-linux-armhf.so.3
# 重新拷贝实体文件
cp ld-linux-armhf.so.3 /home/duan/linux/nfs/rootfs/lib/
2.3.4 拷贝额外的库文件
有些库文件存放在交叉编译器的lib目录下,也需要一并拷贝:
bash复制cd /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
2.3.5 拷贝usr/lib下的库文件
某些特定的库文件存放在usr/lib目录下:
bash复制cd /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
2.4 库文件裁剪建议(进阶)
虽然文中采用了"全量拷贝"的方式简化操作,但在实际产品开发中,我们需要对库文件进行裁剪以节省空间。常用的裁剪方法包括:
- 使用
ldd命令分析BusyBox依赖的库文件,只保留必要的 - 通过
strip命令去除库文件中的调试信息 - 使用
buildroot或yocto等工具链自动优化
例如,查看BusyBox依赖的库:
bash复制arm-linux-gnueabihf-readelf -d busybox | grep NEEDED
3. 创建其他必要目录
一个完整的根文件系统还需要以下标准目录:
3.1 基础目录结构
bash复制cd /home/duan/linux/nfs/rootfs
mkdir -p dev proc mnt sys tmp root etc var home
各目录的作用:
| 目录 | 用途 |
|---|---|
| dev | 设备节点文件 |
| proc | 进程和内核信息接口 |
| mnt | 临时挂载点 |
| sys | sysfs虚拟文件系统 |
| tmp | 临时文件 |
| root | root用户的家目录 |
| etc | 系统配置文件 |
| var | 可变数据文件 |
| home | 普通用户家目录 |
3.2 目录权限设置
某些特殊目录需要设置正确的权限:
bash复制chmod 1777 tmp # 设置粘滞位,防止用户删除他人文件
chmod 755 root # 确保root目录安全
4. 常见问题与解决方案
4.1 库文件缺失导致程序无法运行
现象:执行程序时报错"not found"或"missing library"
排查步骤:
-
使用
file命令确认程序架构是否匹配:bash复制
file busybox应显示"ARM"架构
-
使用
ldd检查依赖库:bash复制
arm-linux-gnueabihf-ldd busybox -
检查库文件路径是否正确,特别是
ld-linux.so的路径
4.2 符号链接问题
现象:库文件存在但程序仍然报错
解决方案:
- 确保关键库文件(如ld-linux)不是符号链接
- 使用
readelf检查动态段:bash复制
arm-linux-gnueabihf-readelf -d busybox
4.3 空间不足问题
优化建议:
- 删除不必要的库文件(如静态库.a文件)
- 使用
strip减小文件大小:bash复制arm-linux-gnueabihf-strip busybox find lib -name "*.so" | xargs arm-linux-gnueabihf-strip
5. 下一步工作
现在我们已经有了一个基本的根文件系统框架,接下来的工作包括:
- 创建设备节点(特别是console和null设备)
- 添加基本的配置文件(如inittab、fstab等)
- 设置用户和权限
- 测试系统启动流程
在实际项目中,我通常会先用这个最小系统启动开发板,确认基本功能正常后,再逐步添加其他组件。这样可以快速定位问题,避免一次性添加太多内容导致难以调试。