虚拟文件系统
在 Linux 文件系统中,用户空间、系统调用、虚拟机文件系统、缓存、文件系统以及存储之间存在着紧密的关系。 如下图:
在操作系统中,文件系统起到了重要的作用,它们负责管理操作系统中的文件和目录。然而,不同的文件系统有着不同的实现方式和存储位置。为了提供一个统一的接口给用户,操作系统引入了虚拟文件系统(Virtual File System,VFS)作为中间层。
VFS 定义了一组通用的数据结构和标准接口,使得程序员无需了解具体文件系统的工作原理,只需要了解 VFS 提供的接口即可进行文件操作,其实连提供的接口各种编程语言都替我们封装好了,只需要调用一些方法就完事了。
Linux 支持多种文件系统,根据存储位置的不同,可以将文件系统分为三类。
- 磁盘的文件系统,它将数据直接存储在磁盘中,例如 Ext 2/3/4、XFS 等。
- 内存的文件系统,这类文件系统的数据存储在内存中,如 /proc 和 /sys 文件系统,读写这些文件实际上是读写内核中相关的数据。
- 网络的文件系统,用于访问其他计算机主机的数据,例如 NFS、SMB 等。
为了正常使用文件系统,首先需要将其挂载到某个目录上。例如,在 Linux 系统启动时,会将文件系统挂载到根目录,从而使文件系统可用。
文件的物理结构
操作系统负责管理磁盘中的数据,并将其呈现为易读的形式,使我们不需要关心数据的具体存放位置及其存储方式。操作系统背后的机制将数据存储在磁盘上,以便我们可以方便地访问和操作。
在操作系统的辅助下,我们看下文件的物理结构是如何在磁盘中存储的。
文件块
我们知道,物理磁盘上存储的最小单位是扇区,通常为512字节。这意味着即使一个数据不足512字节,它仍然会占用512字节的磁盘空间。然而,由于扇区的大小较小,会导致读写效率降低。
为了方便管理和访问文件,操作系统引入了逻辑块的概念。几乎所有的文件系统都会将文件分割成固定大小的块来存储,前面我们说过通常一个块的大小为4KB。如果磁盘的扇区大小为512字节,而文件系统的块大小为4KB,那么文件系统的存储单元就是8个扇区。这也解释了为什么文件的大小和占用空间之间存在差异。文件的大小指的是文件本身的实际大小,但并不一定等于占用的空间大小。因为不管文件的大小是否达到4KB,只要有数据,都会分配给它一个块进行存储。
需要注意的是,在Windows的NTFS文件系统中,如果写入的数据很小,小于1KB,它将被存储在文件表中,而不是以4KB为单位的块中。但一旦数据超过1KB,将会分配4KB的存储空间。
内存管理也采用类似的逻辑块的概念。文件的逻辑地址也被分为一块块的文件块,逻辑地址由逻辑块号和块内地址组成。用户通过逻辑地址来操作文件,而操作系统负责完成逻辑地址与物理地址的映射,以实现对文件的访问和操作。
文件分配方式
文件分配方式大致可以分为连续分配和非连续分配两种。连续分配是指将文件的数据块连续地存储在磁盘上的相邻区域,类似于Java中的数组。非连续分配则是将文件的数据块分散存储在磁盘上的不同区域,类似于Java中的链表。
连续分配
这种分配方式可以提高访问速度,因为文件的块是连续存储的,所以在访问文件时不需要进行磁头的来回移动,可以直接顺序访问。这种顺序访问的特性使得连续分配适用于访问模式较为顺序的文件,比如视频文件或音乐文件。
那么操作系统如何完成逻辑块与物理块之间的映射呢?
在实际情况中,每个文件都会被放置在一个目录中,无论是最外层的根目录还是用户自己创建的目录,都会有一个对应的目录结构文件,它记录了当前目录下的目录项和文件信息。如图所示:
具体来说,操作系统通过逻辑块号和块内地址的映射关系来实现逻辑块与物理块之间的对应关系,即(逻辑块号,块内地址)-> (物理块号,块内地址)。对于用户访问一个文件的内容,操作系统会通过文件的标识符找到对应的目录项,并通过逻辑块号计算出物理块号,即物理块号 = 起始块号 + 逻辑块号。由于可以根据逻辑块号直接计算出物理块号,所以连续分配方式支持顺序访问和随机访问。
连续分配方式在读写文件时效率较高,因为文件的磁盘块是相邻的,减少了移动磁头的时间。这也是为什么一些中间件或数据库在写文件时采用顺序写的机制,以提高处理速度。
连续空间存放的方式虽然读写效率高,但是缺点也很明显,有「磁盘空间碎片」和「文件长度不易扩展」的缺陷。
然而,连续分配方式也存在明显的缺点,主要是磁盘空间碎片和文件长度不易扩展。当一个文件被删除时,会留下一块空缺,如果新文件的大小小于该空缺的大小,可以将其放置在空缺中。但如果新文件的大小大于所有空缺的总大小,即使磁盘上有足够的空闲空间,也无法存放该文件。在这种情况下,我们可以通过移动已有文件来腾出空间以容纳新文件,但是磁盘上的文件移动是非常耗时的,因此这种方式并不太实际。
另一个问题是文件长度扩展不方便。例如,在上述图示中,如果文件A需要扩大,就需要更多的磁盘空间。然而,唯一的办法就是通过移动文件来腾出足够的空间,而这种方式的效率非常低下。
那么有没有更好的方式来解决上面的问题呢?确实,为了解决连续分配方式的问题,可以采用非连续空间存放方式,如链式存储、索引存储和组织表等方式。这些方式可以克服连续分配方式的空间碎片和文件长度扩展不方便的问题。那这种非连续的分配方式我们下回讲解!
总结
本文主要讨论了操作系统中文件系统的实现和分配方式。首先介绍了虚拟文件系统(VFS)作为中间层,统一了不同文件系统的接口。然后介绍了文件的物理结构,包括文件块和逻辑块之间的映射关系。接着详细讨论了连续分配方式的特点和优缺点,包括顺序访问和随机访问的效率,以及磁盘空间碎片和文件长度扩展不方便的问题。为了知识的消化理解,本章留下的问题我们下一章再详细讲下!
我是努力的小雨,一名 Java 服务端码农,潜心研究着 AI 技术的奥秘。我热爱技术交流与分享,对开源社区充满热情。同时也是一位掘金优秀作者、腾讯云创作之星、阿里云专家博主、华为云云享专家。
💡 我将不吝分享我在技术道路上的个人探索与经验,希望能为你的学习与成长带来一些启发与帮助。
🌟 欢迎关注努力的小雨!🌟