LV010-根文件系统简介
一、根文件系统
1. 什么是根文件系统
根文件系统一般也叫做 rootfs,那么什么叫根文件系统?看到“文件系统”这四个字,第一反应就是 FATFS、 FAT、 EXT4、YAFFS 和 NTFS 等这样的文件系统。但是在这里所说的根文件系统却不是那些。
Linux 中的根文件系统更像是一个文件夹或者叫做目录,在这个目录里面会有很多的子目录。根目录下和子目录中会有很多的文件,这些文件是 Linux 运行所必须的,比如库、常用的软件和命令、设备文件、配置文件等等。相当于 windows 下的 C 盘,保存了系统启动后的应用程序和系统配置。
对于根文件系统专业的解释,百度百科上是这么说的:根文件系统首先是内核启动时所 mount(挂载)的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。
展开细说就是,根文件系统首先是一种文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但是相对于普通的文件系统,它的特殊之处在于,它是内核启动时所挂载(mount)的第一个文件系统,内核代码的映像文件保存在根文件系统中,系统引导启动程序会在根文件系统挂载之后从中把一些初始化脚本(如 rcS, inittab)和服务加载到内存中去运行。
Tips:
(1)百度百科上说内核代码镜像文件保存在根文件系统中,但是我们要明白文件系统和内核是完全独立的两个部分,我们嵌入式 Linux 并没有将内核代码镜像保存在根文件系统中,而是保存到了其他地方,比如 NAND Flash 的指定存储地址、EMMC 专用分区中。
(2)根文件系统 包含了 Linux 系统启动和运行所必需的文件和目录。这些文件和目录对于系统的初始化和后续运行至关重要。
Linux 启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。成功之后可以自动或手动挂载其他的文件系统。因此,一个系统中可以同时存在不同的文件系统。
Tips:在 Linux 中将一个文件系统与一个存储设备关联起来的过程称为挂载(mount)。使用 mount 命令将一个文件系统附着到当前文件系统层次结构中(根)。在执行挂装时,要提供文件系统类型、文件系统和一个挂装点。根文件系统被挂载到根目录下“/”上后,在根目录下就有根文件系统的各个目录,文件:/bin /sbin /mnt 等,再将其他分区挂接到/mnt 目录上,/mnt 目录下就有这个分区的各个目录和文件。
2. 根文件系统的重要性
根文件系统和 Linux 内核是分开的,单独的 Linux 内核是没法正常工作的,必须要搭配根文件系统。 如果不提供根文件系统, Linux 内核在启动的时候就会提示内核崩溃(Kernel panic)的提示。
根文件系统是其他文件系统的根,没有这个“根”,其他的文件系统或者软件就无法工作。比如我们常用的 ls、 mv、 ifconfig 等命令其实就是一个个小软件,只是这些软件没有图形界面,而且需要输入命令来运行。这些小软件就保存在根文件系统中,这些小软件是怎么来的呢?后边的笔记就是构建自己的根文件系统的过程,这个根文件系统是满足 Linux 运行的最小根文件系统,后续我们可以根据自己的实际工作需求不断的去填充这个最小根文件系统,最终使其成为一个相对完善的根文件系统。
根文件系统包含系统启动时所必须的目录和关键性的文件,以及使其他文件系统得以挂载(mount)所必要的文件。例如:
- init 进程的应用程序必须运行在根文件系统上;
- 根文件系统提供了根目录“/”;
- linux 挂载分区时所依赖的信息存放于根文件系统/etc/fstab 这个文件中;
- shell 命令程序必须运行在根文件系统上,譬如 ls、cd 等命令;
总之:一套 linux 体系,只有内核本身是不能工作的,必须要 rootfs(上的 etc 目录下的配置文件、/bin /sbin 等目录下的 shell 命令,还有/lib 目录下的库文件等···)相配合才能工作。
3. 根文件系统的实质
(1)根文件系统是一种特殊的文件系统。
(2)根文件系统属于用户进程,和内核无关。
(3)根文件系统具有一定的格式。
二、根文件系统里有什么?
1. 有什么?
我们进入 ubuntu 的根目录,这其实也就是 ubuntu 的根文件系统了:

会发现里边有大量的子目录,子目录中还会有相应的子目录,这里我们只关心我们可能会用到的几个。
| 目录名称 | 说明 |
|---|---|
| /bin | bin 文件就是可执行文件。所以此目录下存放着系统需要的可执行文件,一般都是一些命令,比如 ls、 mv 等命令。此目录下的命令所有的用户都可以使用。 |
![]() | |
| /sbin | 该目录下存放系统命令,即只有系统管理员(俗称最高权限的 root)能够使用的命令,系统命令还可以存放在/usr/sbin,/usr/local/sbin 目录下,/sbin 目录中存放的是基本的系统命令,它们用于启动系统和修复系统等,与/bin 目录相似,在挂接其他文件系统之前就可以使用/sbin,所以/sbin 目录必须和根文件系统在同一个分区中。 /sbin 目录下常用的命令有:shutdown、reboot、fdisk、fsck、init 等,本地用户自己安装的系统命令放在/usr/local/sbin 目录下。 |
![]() | |
| /dev | dev 是 device 的缩写,所以此目录下的文件都是和设备有关的,此目录下的文件都是设备文件(设备节点)。在 Linux 下一切皆文件,即使是硬件设备,也是以文件的形式存在的,比如 /dev/ttymxc0(I.MX6ULL 根目录会有此文件)就表示 I.MX6ULL 的串口 0,我们要想通过串口 0 发送或者接收数据就要操作文件 /dev/ttymxc0 ,通过对文件/dev/ttymxc0 的读写操作来实现串口 0 的数据收发。即通过读写某个设备文件操作某个具体硬件。 |
![]() | |
| /etc | 该目录下存放着系统主要的配置文件,例如人员的账号密码文件、各种服务的其实文件等。一般来说,此目录的各文件属性是可以让一般用户查阅的,但是只有 root 有权限修改。对于 PC 上的 Linux 系统,/etc 目录下的文件和目录非常多,这些目录文件是可选的,它们依赖于系统中所拥有的应用程序,依赖于这些程序是否需要配置文件。在嵌入式系统中,这些内容可以大为精减。我们可以进入 ubuntu 的这个目录中看一下,会发现里面的配置文件非常多。但是在嵌入式 Linux 下此目录会很简洁。 |
![]() | |
| /lib | lib 是 library 的简称,也就是库的意思,因此此目录下存放着 Linux 所必须的库文件。这些库文件是共享库,命令和用户编写的应用程序要使用这些库文件。 |
![]() | |
| /mnt | 临时挂载目录,一般是空目录,可以在此目录下创建空的子目录,比如/mnt/sd、 /mnt/usb,这样就可以将 SD 卡或者 U 盘挂载到 /mnt/sd 或者 /mnt/usb 目录中。这里的 hgfs 就是 vmware 中 ubuntu 与 windows 共享目录所在的位置。 |
![]() | |
| /proc | 此目录一般是空的,当 Linux 系统启动以后会将此目录作为 proc 文件系统的挂载点, proc 是个虚拟文件系统,没有实际的存储设备。 proc 里面的目录,文件都是由内核临时生成的,用来表示系统的运行状态,也可以操作其中的文件控制系统。 |
![]() | |
| /usr | 要注意, usr 不是 user 的缩写,而是 Unix Software Resource 的缩写,也就是 Unix 操作系统软件资源目录。既然是软件资源目录,因此/usr 目录下也存放着很多软件,一般系统安装完成以后此目录占用的空间最多。usr 目录的内容可以存在另一个分区中,在系统启动后再挂接到根文件系统中的/usr 目录下。里面存放的还有一些共享、只读的程序和数据,这表明/usr 目录下的内容可以在多个主机间共享,这些主要也符合 FHS 标准的。/usr 中的文件应该是只读的,其他主机相关的,可变的文件应该保存在其他目录下,比如/var。/usr 目录在嵌入式中可以精减。 |
![]() | |
| /var | 与/usr 目录相反,/var 目录中存放可变的数据,比如 spool 目录(mail, news),log 文件,临时文件。 |
![]() | |
| /sys | 系统启动以后此目录作为 sysfs 文件系统的挂载点, sysfs 是一个类似于 proc 文件系统的特殊文件系统, sysfs 也是基于 ram 的文件系统,也就是说它也没有实际的存储设备。此目录是系统设备管理的重要目录,此目录通过一定的组织结构向用户提供详细的内核数据结构信息。 |
![]() | |
| /opt | 可选的文件、软件存放区,由用户选择将哪些文件或软件放到此目录中。 |
| 无 | |
| /home | 系统默认的用户文件夹,它是可选的,对于每个普通用户,在/home 目录下都有一个以用户名命名的子目录,里面存放用户相关的配置文件。 |
![]() | |
| /root | 系统管理员(root)的主文件夹,即是根用户的目录,与此对应,普通用户的目录是/home 下的某个子目录。 |
![]() |
2. 小结
对于嵌入式 Linux 系统的根文件系统来说,一般可能没有上面所列出的那么复杂,比如嵌入式系统通常都不是针对多用户的,所以/home 这个目录在一般嵌入式 Linux 中可能就很少用到,而/boot 这个目录则取决于所使用的 BootLoader 是否能够重新获得内核映像从我们的根文件系统在内核启动之前。一般说来,只有/bin,/dev,/etc,/lib,/proc,/var,/usr 这些需要的,而其他都是可选的。
三、常见的根文件系统
根文件系统本质都是一些文件和配置信息组成,之间的界限没有很明确的界定,下面是一些常见的:
| 名称 | 优点 | 缺点 |
| buildroot | 构建简单,容易理解,能构建完整镜像。 | 无包管理工具 |
| Ubuntu | 构建方便,支持包管理工具,支持 ROS 1.x 等机器人操作系统 | 构建的文件系统较大 |
| Debian | 构建方便,支持包管理工具,支持可视化界面 | 构建的文件系统较大 |
| yocto | 支持的框架较多,能构建完整镜像 | 配置复杂,不易于新手操作 |
| busybox | 体积小,支持常用命令,常用于定制特定功能的小系统 | 功能不全,无包管理工具 |
四、uClibc 与 glibc 的差异
我们做嵌入式开发的话,肯定会用到 C 库,C 库存在于根文件系统,我们这里简单了解下。
glibc 和 libc 都是 Linux 下的 C 函数库,libc 是 Linux 下的 ANSI C 的函数库;glibc 是 Linux 下的 GUN C 的函数库;GNU C 是一种 ANSI C 的扩展实现。ANSI C 是基本的 C 语言函数库,包含了 C 语言最基本的库函数。在写程序时,需要用到很多 c 语言的库函数,这些所有的库函数整合起来,就是对应的 C 语言(标准)函数库。
目前在普通 GNU/Linux 系统中所用的 C 语言标准库,叫做 glibc。它的功能很全,函数很多,但是就是因为代码太多,编译出来的函数库的大小也很大,占用的资源也很多,可以简单地认为 glibc 就是为了实现完整功能设计的。
由于在嵌入式系统中,也需要 C 语言写代码实现特定功能,因此需要用到 C 语言函数库,但是由于嵌入式系统中,一般资源比较有限,所以不适合直接使用太占用资源的 glibc。uClibc 是一个面向嵌入式 Linux 系统的小型的 C 标准库,最初 uClibc 是为了支持 uClinux 而开发,这是一个不需要内存管理单元(MMU)的 Linux 版本。uClibc 比一般用于 Linux 发行版的 C 库 GNU C Library (glibc)要小得多, 因此 uClibc 专注于嵌入式 Linux,除此之外 uClibc 比 glibc 更可配置,这意味着开发人员可以根据功能与空间需求进行裁剪。
简单总结以下几点:
(1)uClibc 比 glibc 占用的资源小,虽然 uClibc 和 glibc 在已有的接口上是兼容的,而且采用 uClibc 编译应用程序比采用 glibc 编译应用程序要更方便,但是 uClibc 并没有包括 glibc 中的所有接口实现,因此有些应用可能在 uClibc 中不能编译。
(2)uClibc 在可配置性上比 glibc 要好。
关于 uClibc 与 glibc 更多的差异比较信息请看:Comparison of C/POSIX standard library implementations for Linux (etalabs.net)
五、制作工具?
根文件系统里面就是一堆的可执行文件和其他文件组成的?难道我们得一个一个的从网上去下载这些文件?显然这是不现实的!那么有没有人或者组织专门干这个事呢?他们负责“收集”这些文件,然后将其打包,像我们这样的开发者可以直接拿来用。
答案当然是有的,也会有多种工具来帮助我们构建根文件系统,例如 busybox 、Buildroot 、Yocto 等,其中我们常用的就是前两个,最后的 Yocto 的编译是比较复杂的,一般见得多的还是 busybox。
但是其实 busybox 构建的根文件系统不齐全,很多东西需要我们自行添加,比如 lib 库文件。在我们后面的驱动开发中很多第三方软件也需要我们自己去移植,这些第三方软件有很多又依赖其他的库文件,导致移植过程非常的繁琐。busybox 仅仅只是帮我们构建好了一些常用的命令和文件,像 lib 库、 /etc 目录下的一些文件都需要我们自己手动创建,busybox 构建的根文件系统默认没有用户名和密码设置。在后续的学习,我们还要自己去移植一些第三方软件和库,比如 alsa、 iperf、 mplayer 等等。
buildroot 就会好很多,它比 busybox 更上一层楼, buildroot 不仅集成了 busybox,而且还集成了各种常见的第三方库和软件,我们需要什么就选择什么, buildroot 极大的方便了嵌入式 Linux 开发人员构建实用的根文件系统。
从 busybox 开始一步一步的构建根文件系统适合学习、了解根文件系统的组成,但是不适合做产品(主要是自己构建的话会有很多不完善、没有注意到的细节)。 buildroot 会帮我们处理好各种细节,根文件系统也会更加的合理、有效。因此在做产品的时候推荐使用 buildroot 来构建自己的根文件系统,当然了,类似 buildroot 的软件还有很多,比如 yocto。
参考资料:











