3. Linux文件系统层次标准
在嵌入式Linux根文件系统构建中,目录结构不是随意摆放文件的“杂物间”,而是遵循一套被广泛接受的约定——FHS(Filesystem Hierarchy Standard,文件系统层次标准)。FHS定义了Linux系统中目录的层级、命名和用途,使应用程序、库、配置和运行时数据能够被系统与开发者以可预期的方式定位。对于嵌入式系统而言,理解FHS不仅是“知道目录长什么样”,更是判断哪些目录必须存在、哪些可以裁剪、哪些需要根据存储介质和启动方式调整的基础。
一、FHS的核心思想与顶层目录
FHS的核心思想可以概括为三点:按用途分类、按可变性区分、按共享性划分。它把文件系统划分为若干顶层目录,每个目录承担明确职责。例如,/bin、/sbin、/lib存放系统启动和基本运行所需的关键程序与库;/etc存放主机专属配置;/usr存放用户态程序与只读数据;/var存放运行中会变化的数据;/dev、/proc、/sys则是设备节点和内核暴露的虚拟文件系统。
FHS还区分了“根文件系统”与“可独立挂载的文件系统”。在桌面发行版中,/usr、/var、/home常被单独分区;在嵌入式系统中,由于Flash容量有限,这些目录往往被合并到同一个只读或可读写分区中,甚至通过符号链接重新组织。
二、各目录用途与嵌入式裁剪原则
在嵌入式根文件系统中,裁剪不是简单删除目录,而是围绕“启动必需、运行必需、调试可选”三个层次做取舍。下面这张表列出了常见目录的用途、是否可裁剪以及典型处理方式。
| 目录 | 主要用途 | 嵌入式裁剪建议 |
|---|---|---|
/bin |
启动和单用户模式所需的基础命令 | 保留 sh、ls、cp、mount 等;其余可合并到 /usr/bin |
/sbin |
系统管理、网络配置、文件系统检查 | 按需保留 ifconfig、route、fsck;调试工具可放入只读分区 |
/lib |
动态链接库、内核模块 | 只保留应用程序实际依赖的 .so;内核模块按硬件裁剪 |
/etc |
系统与应用程序配置 | 保留 fstab、inittab、网络配置;删除开发主机专属配置 |
/usr |
用户态程序、库、共享数据 | 可设为只读;合并 /bin、/sbin、/lib 内容 |
/var |
日志、锁文件、运行时状态 | 挂载到 tmpfs 或可读写分区;限制日志大小 |
/dev |
设备节点 | 由 devtmpfs 自动生成,镜像中只需保留必要静态节点 |
/proc、/sys |
内核与驱动暴露的虚拟文件系统 | 启动脚本中挂载,不占用镜像空间 |
三、方法流程:从FHS到可启动根文件系统
构建一个符合FHS精神、又适合嵌入式约束的根文件系统,通常遵循以下流程:
- 确定启动链需求:内核启动后需要执行哪个init程序?它依赖哪些库和配置文件?
- 建立最小目录骨架:创建
/bin、/sbin、/lib、/etc、/dev、/proc、/sys、/tmp、/var、/usr等目录。 - 填充必需文件:复制BusyBox或Coreutils、C库、内核模块、启动脚本和关键配置。
- 建立符号链接与合并策略:根据空间和只读需求,决定是否将
/bin、/sbin、/lib链接到/usr下。 - 设置挂载点与权限:为
/proc、/sys、/tmp、/var准备挂载脚本,确保运行时目录可写。 - 验证与裁剪:通过启动日志和
ldd、strace检查缺失依赖,逐步删除未使用文件。
例如,在启动脚本中常见如下挂载操作:
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
mount -t tmpfs none /tmp
mount -t tmpfs none /var
这些虚拟文件系统不占用Flash空间,却为系统提供了标准目录语义。若缺少 /proc 或 /sys,许多程序将无法获取系统信息,甚至启动失败。
四、案例与误区复盘
某工业网关项目使用 64MB NAND Flash,最初直接复制桌面发行版的 /etc 和 /usr,导致镜像超过 120MB,且启动时因 /var/log 频繁写入而加速坏块产生。调整方案是:将 /usr 设为只读,/var 和 /tmp 挂载为 tmpfs,/etc 仅保留网络、串口和启动脚本,最终镜像压缩到 28MB,启动时间缩短约 40%。
常见误区:把FHS当成“必须原样保留所有目录”的硬性规定。实际上FHS允许通过符号链接和合并目录来适应只读、小容量场景。另一个误区是忽略 /var 的可写性,导致日志或PID文件写入失败,程序异常退出。
实践建议:在裁剪时先用 ldd 检查可执行文件的库依赖,再用 find 和 du 定位大文件;对 /etc 中的配置逐项确认是否被目标板实际读取。保持“启动必需优先、运行必需保留、调试工具按需”的原则,才能构建出既符合FHS精神又精简可靠的嵌入式根文件系统。