VFS与Ext2文件系统------《深入Linux内核架构》笔记

 

1. VFS简介(Virtual File System, 虚拟文件系统)

Linux内核中支持40多种文件系统,其来源也多种多样:来自MS-DOSFAT文件系统, UFS(Berkeley UNIX), Ext2/3/4, 用于CD-ROMiso9660, 网络文件系统(codaNFS)和虚拟的文件系统(proc)

Linux为了向用户空间(C标准库)提供标准的接口,将所有的文件系统,抽象为统一的文件系统接口----VFS。图1-1 Linux文件系统的结构。

VFS与Ext2文件系统------《深入Linux内核架构》笔记_第1张图片

 

1-1 Linux文件系统的结构

Linux,文件系统主要分为下面3种:

(1)基于磁盘的文件系统(Disk-based Filesystem) 是在非易失介质上存储文件的经典方法,用以在多次会话之间保持文件的内容。如Ext2/3/4 Reiserfs, FAT等。

(2)虚拟文件系统(Virtual Filesystem) 在内核中生成,是一种用户应用程序与内核通信的方法。如proc,它不许要在任何类的硬件设备上分配存储空间,所有的信息都是动态在内存中开辟和存储。

(3)网络文件系统(Network Filesystem) 是基于磁盘的文件系统和虚拟文件系统之间的折中。这种文件系统允许访问另一台计算机上的数据,该计算机通过网络连接到本地计算机。在这种情况下,数据实际上存储在一个不同系统的硬件设备上。

由于VFS抽象层的存在,用户空间进程不会看到本地文件系统与网络文件系统之间的区别。

2. VFS的模型与结构

VFS不仅为文件系统提供了方法和抽象,还支持文件系统中对象(或文件)的统一视图。并非每一种文件系统都支持VFS中的所有抽象,如FAT,因为其设计没有考虑到此类对象。定义一个最小的通用模型,来支持内核中所有文件系统都实现的那些功能,这是不实际的。因为这样会损失许多本质性的功能特性,或者导致这些特性只能通过特定文件系统的路径访问。

VFS的方案完全相反:提供一种结构模型,包含了一个强大文件系统所具备的所有组件。但该模型只存在于虚拟中,必须使用各种对象和函数指针与每种文件系统适配。所有文件系统的实现都必须提供与VFS定义的结构配合的例程,以弥合两种视图之间的差异。

VFS是由基于经典文件系统的结构衍化而来,所以VFSExt类文件系统类似,从而在处理Ext类文件系统的时候,ExtVFS之间的转换,几乎不会损失时间。图1-2 底层为Ext2VFS结构

 

VFS与Ext2文件系统------《深入Linux内核架构》笔记_第2张图片

图 1-2 底层为Ext2VFS结构

图1-2中绿色方框的部分为Ext2实现的部分,而Ext2中用户表示目录的结构为ext2_dir_entry_2

 

struct ext2_dir_entry_2 {
	__le32	inode;		/* Inode number */
	__le16	rec_len;		/* Directory entry length */
	__u8	name_len;	/* Name length */
	__u8	file_type;
	char	name[EXT2_NAME_LEN];	/* File name */
};

其保存在inode->imapping所指向的空间中。对于dentry_operations,Ext2无须实现本地化,因为采用默认的dentry_operations已能完成所需工作。例,对于FAT,由于在比较两个文件名是否相等时,需要忽略大小写,则必须实现本地化,参见msdos_dentry_operations。图1-2中所涉及的结构体请参考书中的第89Linux内核源代码

以下以查询一个目录为例(path_lookup函数),进行简要说明。其中底层文件系统为Ext2

1. 首先,内核使用nameidata实例规定查找起点,如果名称以/开始,则使用当前根目录的dentryvfsmount实例;否则,从当前进程的task_struct获得当前的工作目录。

2. 检查当前路径分量对应的cur_inode的权限,计算路径中next_dir的散列值,。

3. 处理...,该任务委托给follow_dotdot函数。

4. 根据2中的散列值和cur_inode的dentry,通过d_hash函数计算出next_dir的dentrydentry缓存中可能存在其的链表,遍历链表,如果存在,跳至i,如果不存在需要调用real_lookup通过cur_inode查找。

5. real_lookup函数通过dentry->i_op->lookup调用ext2_lookup函数实现对cur_inode->i_mapping内存空间的遍历,来查找目录是否存在于该cur_inode中。如果存在,新建next_dir的dentry项,并存入dentry缓存,跳至i;不存在,返回错误。

i. next_dir的inode更新cur_inode,并得到一下个需要查找的目录,返回2。如果查找完毕,则成功。

注:在通过当前目录查找某个子目录是否存在的时候,使用了ext2_lookup函数直接遍历该目录的数据域,如果是文本文件会咋样呢?文本文件在建立的时候对其对应的inodei_op域的初始化为ext2_file_inode_operations。所以文本文件的inode->i_op->lookup将为NULL

文中部分内容涉及自己对文件系统的理解,难免有不足之处,请多谅解。


你可能感兴趣的:(linux)