嵌入式文件系统目录bin、sbin、dev、etc 核心目录作用上回说到根文件系统是内核的办公室。今天我们走进这间办公室挨个看看每个工位——也就是每个核心目录——到底是干什么的。引言一个嵌入式根文件系统看起来目录不多但每个目录都有明确的职责分工。搞懂这些目录的作用是定制根文件系统的基础。本文将逐一拆解/bin、/sbin、/dev、/etc等核心目录的功能并给出嵌入式精简目录的实践建议。一、/bin —— 基本命令目录/bin是binary的缩写存放的是所有用户都可以使用的基本命令。这些命令在系统启动和单用户模式下都需要可用因此不能放在单独的分区上。典型内容命令作用shShell 解释器ls列出目录内容cp复制文件mv移动/重命名文件rm删除文件cat查看文件内容echo输出文本mount挂载文件系统ps查看进程在嵌入式系统中这些命令几乎全部由BusyBox通过软链接方式提供。也就是说/bin/ls实际上是指向/bin/busybox的符号链接# 查看BusyBox命令的软链接ls-la/bin/ls lrwxrwxrwx1root root7Jan100:00 /bin/ls -busyboxls-la/bin/cat lrwxrwxrwx1root root7Jan100:00 /bin/cat -busybox这种设计非常巧妙——一个不到 2MB 的 busybox 二进制文件通过软链接就能模拟出上百个常用命令。二、/sbin —— 系统管理命令目录/sbin存放的是系统管理类命令通常需要 root 权限才能执行。s代表system。典型内容命令作用init系统初始化进程PID1reboot重启系统poweroff关机ifconfig配置网络接口route路由表管理mdev设备节点管理BusyBox版udevfsck文件系统检查swapon启用交换分区/bin 和 /sbin 的区别简单理解/bin给普通用户用/sbin给管理员用。不过在嵌入式系统中通常只有 root 一个用户这个界限并不重要。FHS 标准做出这个区分主要是为了在多用户系统中保证安全性。三、/dev —— 设备文件目录/dev是 Linux 一切皆文件理念的集中体现。系统中的每个硬件设备在这里都对应一个文件。常见设备节点设备节点对应硬件类型/dev/console系统控制台字符设备/dev/null黑洞设备丢弃所有写入字符设备/dev/zero零设备读取返回无限零字节字符设备/dev/ttyS0串口0字符设备/dev/mmcblk0SD/eMMC 存储设备块设备/dev/mtdblock0NAND Flash 分区块设备/dev/fb0Framebuffer 显示设备字符设备/dev/input/event0输入设备按键、触摸屏字符设备设备节点的创建方式桌面 Linux 使用udev在运行时动态创建设备节点。嵌入式系统中通常有两种方式方式一静态创建mknod# 创建 console 设备节点主设备号5次设备号1mknod-m622/dev/console c51# 创建 null 设备节点mknod-m666/dev/null c13# 创建 ttyS0 串口设备mknod-m660/dev/ttyS0 c464其中c表示字符设备b表示块设备。静态创建的缺点是必须提前知道所有设备号。方式二mdev 动态管理mdev 是 BusyBox 提供的轻量级设备管理器通过内核的 uevent 机制动态创建设备节点# 在 /etc/init.d/rcS 中启动 mdevecho/sbin/mdev/proc/sys/kernel/hotplug mdev-s第一行告诉内核当有设备插拔事件时调用/sbin/mdev处理。第二行mdev -s扫描 sysfs 并为当前已存在的设备创建节点。四、/etc —— 配置文件目录/etc是根文件系统中最重要的目录之一存放所有系统配置文件。这些文件都是纯文本格式可以直接用 vi 编辑。嵌入式系统必备配置文件文件作用/etc/inittabinit 进程配置定义启动级别、执行脚本/etc/fstab文件系统挂载表/etc/init.d/rcS系统启动脚本/etc/profileShell 环境变量配置/etc/hostname主机名/etc/passwd用户信息/etc/group用户组信息/etc/shadow用户密码加密核心配置文件示例/etc/inittabBusyBox init 配置# 格式: id:runlevels:action:process # id设备名, runlevels运行级别(忽略), action动作, process执行的程序 # 系统初始化 ::sysinit:/etc/init.d/rcS # 重启时执行 ::restart:/sbin/init # 关机时执行 ::shutdown:/bin/umount -a -r # 串口控制台交互 ttyS0::respawn:/bin/sh # CtrlAltDel 重启 ::ctrlaltdel:/sbin/reboot/etc/init.d/rcS启动脚本#!/bin/sh# 挂载 proc 和 sysfsmount-tproc proc /procmount-tsysfs sysfs /sys# 创建 /dev 目录下的设备节点mount-ttmpfs tmpfs /devecho/sbin/mdev/proc/sys/kernel/hotplug mdev-s# 配置网络ifconfigeth0192.168.1.100 netmask255.255.255.0 up# 设置主机名hostnamemyboard/etc/profile环境变量# 环境变量配置exportPATH/bin:/sbin:/usr/bin:/usr/sbinexportLD_LIBRARY_PATH/lib:/usr/libexportHOME/rootexportPS1[root\h \W]# # 设置别名aliasllls -laliaslals -la五、/lib —— 共享库目录/lib存放程序运行所需的动态链接库。如果你的程序是动态编译的运行时就需要从/lib中加载.so文件。常见库文件库文件作用libc.so.*C 标准库最核心libm.so.*数学库libpthread.so.*线程库libdl.so.*动态加载库ld-linux*.so.*动态链接器查看程序依赖的库# 使用 arm-linux-gnueabihf 交叉工具链查看依赖arm-linux-gnueabihf-readelf-dbusybox|grepNEEDED# 输出示例# 0x00000001 (NEEDED) Shared library: [libm.so.6]# 0x00000001 (NEEDED) Shared library: [libc.so.6]六、/proc 和 /sys —— 虚拟文件系统挂载点这两个目录本身是空的需要手动挂载虚拟文件系统后才有内容。/procprocfs提供内核和进程的状态信息/syssysfs提供设备和驱动的层次结构信息# 查看CPU信息cat/proc/cpuinfo# 查看内存使用情况cat/proc/meminfo# 查看挂载的文件系统cat/proc/mounts# 查看I2C设备ls/sys/class/i2c-dev/七、嵌入式精简目录结构对于一个最小化嵌入式根文件系统目录可以大幅精简rootfs/ ├── bin/ # busybox 软链接 ├── sbin/ # init, mdev, ifconfig 等 ├── etc/ │ ├── inittab │ ├── fstab │ ├── init.d/ │ │ └── rcS │ ├── profile │ └── passwd ├── lib/ # libc.so, libm.so 等 ├── dev/ # console, null, ttyS0 ├── proc/ # 空目录 ├── sys/ # 空目录 ├── tmp/ # 空目录 └── var/ └── log/ # 日志目录对比桌面系统精简掉了/usr大部分程序直接放/bin、/home只有 root 用户、/root直接用/作为主目录、/boot内核和设备树单独存放在 Flash 分区。总结根文件系统的每个目录都有明确的职责/bin和/sbin提供命令/dev提供设备接口/etc提供配置/lib提供库支撑。嵌入式系统在遵循 FHS 标准的基础上可以做大幅精简——去掉不必要的目录和文件只保留系统运行的最小集合。理解了这些目录的作用后面用 BusyBox 制作根文件系统时就不会一头雾水了。