在Linux内核中,虚拟文件系统(Virtual File System,VFS)是其中一个至关重要的组件
VFS不仅为用户态应用程序提供了一个统一的文件系统接口,还为底层多种文件系统的实现提供了抽象化的操作接口
本文将深入探讨Linux VFS的源码,揭示其内部机制和工作原理
VFS概述 虚拟文件系统(VFS)是Linux内核中的一个核心组件,负责处理与文件和文件系统相关的所有系统调用
作为内核与用户态应用程序之间的桥梁,VFS为用户提供了一个统一的文件操作接口,而无需关心底层文件系统的具体实现
这种抽象机制使得Linux能够支持多种文件系统类型,如ext4、XFS、FAT等,并且可以在运行时动态地加载和卸载这些文件系统
VFS数据结构 VFS涉及的数据结构相对复杂,但有几个关键的结构体在VFS的实现中起到了至关重要的作用
1.file_system_type:这个结构体表示一种文件系统类型,如ext2、ext4等
它包含了文件系统的名称、标志位、挂载函数、卸载函数等关键信息
struct file_system_type{ constchar name; intfs_flags; int(init_fs_context)(struct fs_context ); const struct fs_parameter_specparameters; struct dentry(mount)(struct file_system_type , int, const char , void); void(kill_sb)(struct super_block ); structmodule owner; // 其他成员... }; 2.super_block:这个结构体代表一个已经挂载的文件系统实例
它包含了文件系统的控制信息,如文件系统类型、大小、所有inode对象等
每个物理的磁盘或硬盘都有一个文件控制块(FCB),而super_block可以看作是FCB的内存映像
3.dentry:这个结构体表示目录项,VFS将目录也当作文件处理
每个dentry都有一个inode,但其操作函数与普通文件操作函数不同
dentry的主要用途是建立文件名和inode之间的联系,以提高文件访问效率
4.inode:这个结构体包含了内核在操作文件或目录时需要的全部信息
对于UNIX风格的文件系统,这些信息可以根据需要从磁盘索引结点直接读入或写回磁盘
在Linux中,每个文件(和目录)都有且只有一个对应的inode
5.file:这个结构体从进程的角度表示一个打开的文件
它包含了文件的当前偏移量、访问模式、指向文件操作函数的指针等信息
VFS工作原理 文件系统注册 在挂载某个文件系统实例之前,Linux必须支持该文件系统
换句话说,需要将该文件系统注册到内核中
这是通过`register_filesystem()`函数实现的
Linux使用链表管理注册的文件系统,所有的文件系统都被链接到一个链表上
`register_filesystem()`函数将一个文件系统注册到全局链表`file_systems`上,如果已经存在,则返回-EBUSY,表示注册失败
int register_filesystem(structfile_system_type fs) { int res = 0; structfile_system_type p; // 检查文件系统名称是否包含非法字符,检查是否已经存在等 // ... write_lock(&file_systems_lock); p = find_filesystem(fs->name, strlen(fs->name)); if(p) { res = -EBUSY; }else { p = fs; } write_unlock(&file_systems_lock); return res; } 文件系统挂载 文件系统的挂载是通过`mount`系统调用发起的
在挂载过程中,内核需要执行一系列操作,包括读取文件系统的超级块和inode信息、建立VFS的数据结构等
挂载完成后,新的文件系统被集成到现有的目录树中,形成一个单一的文件系统层次结构
在Linux中,每个挂载点都对应一个`vfsmount`结构体,该结构体描述了挂载点的相关信息,如父文件系统、挂载点在父文件系统中的dentry、挂载的文件系统等
struct mount{ structhlist_node mnt_hash; structmount mnt_parent; struct dentrymnt_mountpoint; struct vfsmount mnt; // 其他成员... }; 文件访问 当用户进程访问一个文件时,它会通过标准的文件操作接口(如`open`、`read`、`write`等)发起系统调用
这些系统调用最终会被VFS拦截,并根据文件的inode信息找到对应的文件系统实现,然