1.rootfs概述

Linux 秉承"一切皆文件"的设计哲学。
文件系统:(File System)是一种用于组织、存储和管理文件及数据的机制,旨在提升数据存取的效率与便利性。 常见示例包括 Windows 平台中的 FAT、FAT32、NTFS,以及 Linux 下的 Ext2/3/4、NFS 等。
根文件系统(Root File System)是内核启动时挂载的第一个文件系统。其中存放了内核映像文件,系统引导程序在挂载根文件系统后,会从中加载基本的初始化脚本和服务至内存中运行。
需注意的是,根文件系统并不等同于某一种具体的文件系统类型(如 ext4 或 Btrfs),而更应理解为一种组织规范与内容集合。它可以建立在多种文件系统类型之上,甚至包括 initramfs 这类内存文件系统。
其核心作用包括:
- 提供基础工具(如
/bin
、/sbin
目录下的命令) - 提供配置文件(如
/etc
目录) - 提供库文件(如
/lib
目录) - 提供设备节点(如
/dev
目录) - 提供启动脚本和 Init 程序
rootfs包含了所有应用程序、库、配置文件和启动脚本的集合。它是内核从"内核空间"进入"用户空间"的桥梁。没有它,内核无法启动任何用户进程,系统也就无法使用。
2.从内核到用户空间
嵌入式系统启动的几个环节
- BOOTLOADER:X86架构(BIOS/UEFI ) 、ARM、MIPS等架构(BOOTCODE、UBOOT)
- 内核
- 根文件系统
- APP运行依赖的中间层、库、环境和服务进程。
当内核启动完成挂载rootfs后,就进入roots的启动流程,分为四个阶段。
- 阶段一:内核寻找 Init
挂载根文件系统:内核挂载嵌入式设备上通常较小的根文件系统(可能是 initramfs, cramfs, jffs2, yaffs2 或 ext4)。 寻找第一个用户进程:内核尝试执行 init。顺序通常是:uboot给内核传参的bootargs中有"init=/linuxrc"
- 阶段二:BusyBox Init 的工作流程 (嵌入式系统的核心)
BusyBox 的 init 行为是可配置的,其工作逻辑如上图流程所示。 关键文件:/etc/inittab 作用:BusyBox 的 init 会读取这个文件来指导后续的所有启动步骤。
- 阶段三:执行系统初始化脚本 (/etc/init.d/rcS)
这是进行具体硬件和系统初始化的地方,由 inittab 中的 sysinit 行调用。 内容:/etc/init.d/rcS 通常是一个 Shell 脚本(例如 /bin/sh,也就是 BusyBox 的 shell)。 作用:它负责完成启动所需的所有杂事,例如:挂载文件系统(/etc/fstab)、配置网络、创建设备节点等
- 阶段四:启动登录 Shell(完成启动)
在 rcS 脚本执行完毕后,BusyBox init 会根据 inittab 中的其他配置继续执行。 最常见的是执行 askfirst 或 respawn action 的条目。 这通常会在指定的控制台(如 ttyS0,即串口)上启动一个 登录 Shell (/bin/sh 或 ash)。 标志着系统启动完成。
其中profile 文件是在用户登录 shell(Login Shell)启动时执行的,它属于系统启动流程中非常靠后的"用户空间初始化"阶段。
3.核心目录解析

嵌入式根文件系统的目录结构:(FHS标准) /bin+sbin 提供系统基本操作调试命令(busybox) /dev 提供系统中的设备节点 /lib 提供基本的库文件 /etc 提供系统的初始化脚本和各种配置文件 /proc 提供系统信息接口和内核参数配置接口 /home 存放用户相关的配置文件,存放应用程序 /opt 大型软件存放目录(非强制) /root 根用户的目录 /usr 存放的是共享、只读的程序和数据 /var 临时文件 /mnt 临时挂载某个文件系统的挂接点,通常是空目录 /tmp 临时文件

4.构建根文件系统
嵌入式系统构建rootfs一般有以下步骤:
- 编译/安装busybox,生成/bin、/sbin、/usr/bin、/usr/sbin目录
- 利用交叉编译工具链,构建/lib目录(工具链的动态库)
- 构建/etc目录
- 构建最简化的/dev目录
- 创建其它空目录
- 配置系统自动生成/proc目录
- 利用udev构建完整的/dev目录
- 制作根文件系统的映像文件
BusyBox 是一个集成了一百多个最常用 linux 命令和工具的软件。BusyBox 包含了一些简单的工具,例如 ls、cat 和echo 等等,还包含了一些更大、更复杂的工具,例 grep、find、mount 以及 telnet。有些人将 BusyBox 称为 Linux 工具里的瑞士军刀。简单的说 BusyBox 就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令,也包含了 Android 系统的自带的shell。
当前已经有比较好用的嵌入式系统自动构建框架可以自动生成根文件系统,比如buildroot,后续文章会进一步介绍。

5.镜像格式与打包工具
rootfs常用的打包镜像有三种,如下表所示。

类别一:压缩归档格式 (无文件系统元数据) 这种格式只是将根文件系统的所有文件二进制拼接并压缩,不具备块设备文件系统的特性(如 inode 表、块位图、日志等)。它需要被解压到另一个文件系统(如 ext4)上才能使用,或者由内核在启动初期直接解压到内存中。
cpio + gzip (.cpio.gz) 特点:
- 是 initramfs/initrd 的标准格式。内核在启动阶段原生支持解压并读取 cpio 归档文件。
- 结构简单,加载速度极快。
类别二:块设备镜像格式 (包含文件系统元数据) 这种格式是一个完整的、包含元数据的文件系统镜像,可以直接被内核挂载为根文件系统,也可以写入到块设备(如 SD 卡、eMMC、硬盘)的某个分区。 ext4 (.img, .ext4) 特点:
- 最常用的可读写根文件系统格式。具有日志功能,意外断电不易导致文件系统损坏。
- 镜像大小可以是固定的,也可以是稀疏文件(sparse file)以节省空间。
SquashFS (.squashfs) 特点:
- 只读、高压缩率的文件系统。
- 是几乎所有 Live CD/USB(如 Ubuntu Live)和 OpenWrt 等嵌入式系统的首选。它将根文件系统高度压缩后,系统运行时直接解压到内存中访问,速度快且节省存储空间。
- 通常与一个可读写的 overlayfs 结合使用,来实现对根文件系统的修改(如保存设置)。
类别三:专用闪存文件系统格式 专为原始(Raw) NOR 和 NAND Flash 芯片设计,考虑了擦写次数(磨损均衡)、坏块管理等特性。
JFFS2 (Journaling Flash File System Version 2) 特点:
- 主要用于 NOR Flash。支持压缩、日志(崩溃安全)、磨损均衡。
UBIFS (Unsorted Block Image File System) 特点:
- 用于 NAND Flash,比 JFFS2 更先进,支持更大的存储容量和更好的性能。它需要先构建一个 UBI 卷。
以cpio为例,常见的打包脚本为:
bash
#打包与压缩
cd ../rootfs/
#创建文件系统归档,将目录结构打包成单个文件---内核需 cpio 支持
find . | cpio -o -H newc > ./../script/initramfs.cpio
cd -
#对 CPIO 归档进行高效压缩,优化启动时的解压速度
lzop -1 ./initramfs.cpio
#为压缩后的文件系统添加 U-Boot 头,使其成为可引导的 RAM 磁盘镜像
mkimage -A arm -T ramdisk -C none -n 'initramfs' -d ./initramfs.cpio.lzo ./rootfs.gz
比较推荐的方式是增量式的打包方式,用busybox或者buildroot构建一个基础版本的根文件系统,然后将自己开发的驱动、库、工具放在增量目录,打包时解压基础包并合并增量文件,最后进行打包压缩形成最终的rootfs。