系列文章目录
第一章 小白快速了解文件系统
第二章 Linux 文件系统基础理论知识详解
前言
在明白了文件系统的基本概念后,我们就深入Linux,从底层了解Linux的文件系统的基础实现原理,如果还不清楚文件系统是什么,可以看 第一章 小白快速了解文件系统
实验环境:centos7
一、进一步了解文件系统的作用
- 字符设备、块设备这些设备驱动的概念都要依靠文件系统来实现
- 字符设备是一种按字节顺序处理数据的设备,它以流的形式处理数据。典型的例子是键盘和串口,它们可以一个字节一个字节地读取或写入数据。字符设备驱动程序负责管理这些设备,并提供相应的接口供操作系统和应用程序使用。
- 块设备是按块(通常是固定大小的块)读取和写入数据的设备。硬盘驱动器(就是一些存储数据的设备)是最常见的块设备,它们以扇区为单位读取和写入数据。块设备驱动程序负责管理这些设备,并提供对文件系统的底层访问。
- 在Linux中有这样一句话,“一切皆文件”,其底层就是由文件系统这一东西所支撑
二、文件系统的重要组件
为了更好地理解文件系统在使用过程中的架构,下面是我画的一张图:
这是从文件系统的整个工作流程的角度画的图,VFS(虚拟文件系统)与文件系统的驱动程序都在内存中,这两相互沟通,文件系统驱动程序再与真正的文件系统进行沟通。
- VFS提供了标准了标准API接口,文件系统驱动程序实现了这些接口,这样VFS与驱动程序就可以沟通了,驱动程序可以识别对应文件系统,这两个相互沟通
- 通过这个结构,我们就可以只与VFS沟通就能管理与使用文件系统,另外,一般我们平常使用的文件系统也就是VFS,所以,这篇文章将会详细而简单地讲解VFS
三、VFS
(1)定义
- VFS(Virtual File System):虚拟文件系统,Linux通过虚拟文件系统管理文件系统,为所有的文件系统提供了统一的接口,每个具体文件系统的访问都要通过VFS定义的接口来实现,即所有Linux的文件系统必须按照VFS定义的方式来实现
(2)作用
- 使得用户应用能够访问不同类型的具体文件系统,比如,一个VFS能够用来访问一个本地或者网络存储设备且同时不会让用户感觉到区别
(3)VFS的主要组件
- VFS本身只存在于内存中,它需要将硬盘上的文件系统抽象到内存中,这是通过 dentry、inode、super_block 来实现的
- super_block(超级块):
- 代表了整个文件系统,保存了整个文件系统最重要的信息,比如 文件系统的块大小、最大文件的尺寸, 这些信息描述了整个文件系统的结构,因此,super_block就是一个文件系统的标志,不同的文件系统的super_block是不同的。超级块存放在硬盘的文件系统的超级块结构中
- 超级块位于文件系统存储设备的特定位置,通常是分区的第一个数据块或保留区域,并且每个文件系统只有一个超级块。它在文件系统启动时被操作系统加载到内存中,并随着文件系统的运行而保持一直可访问的状态。就像下图一样,超级块会像普通的数据一样存放在硬盘上,只不过这些数据特殊,存放的地方特殊
- inode(索引节点):
- 我们知道,数据是存放在文件中的,而文件是存放在内存或者硬盘上的。那么这么多的文件,我们想读取我们需要的那个特定的文件,我们如何找到它呢?很明显,使用inode。
- 一个inode代表一个文件,它保存了文件的大小、创建时间、文件的块大小等参数。inode与super_block之间的关系是,super_block表示文件系统的整体的信息,而inode保存的是一个文件的信息
- 在存储设备中,会存储一张inode表,通过文件的inode号,结合inode表,我们就能找到该文件,在Linux中,使用图中的命令就可以查看根目录 / 下的文件与目录(文件和目录本质上差不多,在inode眼中都是文件,不过我们人为将其区分开来,在inode结构中有区别文件与目录的标志位)的 inode 号
- 下面是inode结构中的一些常见的字段,有助于帮助我们理解,至于dentry是什么,就继续往下看
- dentry(目录项):
- 这个就比较复杂了,dentry 体现了为什么文件系统一般都是以树状的关系进行展示的。 在内存中,每个文件都**至少(可能有多个)**有一个dentry来记录 文件名、父目录、子目录、文件的inode号等,而且每个dentry都有一个唯一的inode号,但每个inode则可能有多个dentry(这种情况是由ln硬链接产生的)。为什么呢?因为这个dentry的作用就是用来 描述路径的,ln硬链接相当多一个访问路径(可以理解为快捷方式),同一个文件,每有一个路径就有一个dentry,指向文件的inode结构的i_dentry字段,我们可以通过这个看一个文件有多少个引用。多说无益,直接上图。
- 首先我们先来看看dentry的结构,看懂了dentry的数据结构你就明白了
- super_block(超级块):
四、整体过程解析
- 对上图过一遍后,接着往下看,这还有一张图,左边我一个树状的目录树,右边是对应的结构,每一个结构都是 dentry。现在让我慢慢讲,给你描述一下目录树的遍历过程。
- 首先,我们能从 super_block 中找到根目录的 inode 号,再通过 inode 找到 根目录对应的dentry(每个dentry都有一个唯一的inode号),这样就找到了根目录。
- 接着通过d_subdirs 可以找到当前目录下所有的 目录和文件,比如 a和b,如果想看a和b下面还有什么,那就查看a和b的subdirs的内容。重复这个过程就能遍历出所有的文件信息
- 如果想往上回退,就可以使用d_parent字段,该字段直接指向父dentry
- 多提一嘴
- dentry 中有一个d_mount字段,这是判断一个 节点是否是挂载点,每一个挂载点下面都是一个新的文件系统,处理逻辑和上面都差不多,如图:
- dentry 中有一个d_mount字段,这是判断一个 节点是否是挂载点,每一个挂载点下面都是一个新的文件系统,处理逻辑和上面都差不多,如图:
总结
本篇介绍了Linux的文件系统的基础理论知识,虽然不多,但足以让我们理解到内存中的文件系统(VFS)是什么以及整个目录树的结构是什么,如何完成树的遍历。
如果有疑问和错误,欢迎发到评论区交流。