目录项、索引节点、逻辑块、超级块,构成 Linux FS 的四大基本要素;
不过,为了支持各种不同的文件系统,Linux Kernel 又在用户进程和文件系统的中间引入抽象层 —— VFS(虚拟文件系统,Virtual File System)
VFS, Virtual File System
VFS 是对具体文件系统的抽象,负责为应用程序提供所有文件系统的统一访问接口,应用程序通过 VFS 提供的接口来访问文件。用户进程和内核的其他子系统,只需要跟 VFS 提供的统一接口进行交互即可,而不需要再关心底层各种文件系统的实现细节:Userspace ⇒ VFS ⇒ (tmpfs/nfs/fs)
VFS 定义了一组所有文件系统都支持的数据结构和标准接口,所有 Linux FS 都必须按照 VFS 定义的方式来实现;
VFS 仅存在于内存中,需要将硬盘文件系统与 VFS 关联,才能完成对文件系统的管理(最终目的)。方法是:VFS 定义 super_block、dentry、inode 结构,应用程序对 VFS 的这些结构进行操作,进而实现应用对硬盘文件系统的操作;
VFS 定义了一组所有文件系统都支持的数据结构和标准接口。这样,用户进程和内核中的其他子系统,只需要跟 VFS 提供的统一接口进行交互就可以了,而不需要再关心底层各种文件系统的实现细节;
System call, VFS, Cache, FS, Block Storage
系统调用、VFS、缓存、文件系统以及块存储之间的关系:
在 VFS 下,Linux 支持各种各样的文件系统,如 Ext4、XFS、NFS 等等。按照存储位置的不同,这些文件系统可以分为三类。
第一类,基于磁盘的文件系统,也就是把数据直接存储在计算机本地挂载的磁盘中。常见的 Ext4、XFS、OverlayFS 等,都是这类文件系统。
第二类,基于内存的文件系统,也就是我们常说的虚拟文件系统。这类文件系统,不需要任何磁盘分配存储空间,但会占用内存。我们经常用到的 /proc 文件系统,其实就是一种最常见的虚拟文件系统。此外,/sys 文件系统也属于这一类,主要向用户空间导出层次化的内核对象。
第三类,网络文件系统,也就是用来访问其他计算机数据的文件系统,比如 NFS、SMB、iSCSI 等。
应用程序
把文件系统挂载到挂载点后,通过挂载点,再去访问它管理的文件。在底层,VFS 提供了一组标准的文件访问接口,这些接口以系统调用的方式,提供给应用程序使用,应用程序将通过 System Call 来访问 VFS,而不与底层的文件系统直接交互;
例如,常用 cat 命令:它首先调用 open(),打开一个文件。然后调用 read(),读取文件的内容;最后再调用 write(),把文件内容输出:
int open(const char *pathname, int flags, mode_t mode); ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); // 如上,open() read() write() 都是系统调用; // cat 命令不需要关系文件系统细节,通过这些系统调用,其将完成对文件的操作;