[深入理解文件系统之四] VFS和vnode

简介:


文件系统的进化史和人类文明的进化有些类似,都是从低级、封闭乃至对抗走向高级、开放和包容。在VFS一统江湖之前,其实还有它的前身FSSFile system Switch)。当时,人们寄希望于它能够兼容各种不同的文件系统。FSS中重要的数据结构mount/,它和传统indoe、文件系统类型的关系如下图:


 

wKioL1i1CKyxuzTcAACyqEPRLLg519.png但是FSS是短命的,被后来SVR3里面引入的vnode快速代替。但我们不能忘记FSS最重要的贡献: 把不同的文件系统以mount的形式挂载起来。

SVR3最早是基于“Vnodes: An architecture for Multiple File-system  Types in Sun Unix”这篇论文,这篇论文提出了实现统一文件系统的四个要求:

1.文件系统依赖层和文件系统非依赖层清晰第分开;

2.支持本地文件系统和NFS/RFS

3.支持NFS 服务器端

4.跨接口的文件系统操作应该是原子的

当然它的实现很复杂。其中一个主要的实现,就是从内核中去掉和具体文件系统相关的全局变量,以保证接口是可重入的。 例如,之前user结构中的u_base/u_count就需要去掉。

新设计的主要架构如下:


wKiom1i1CRbQpo0UAABov2vvipU751.png

那么,vnode和我们现在通常所说的vfs又有何关系呢?关联在代码里又是如何实现的?这就需要了解vnodevfs的数据结构和各自对应的操作。


vnode相关的操作针对vnode,包括vop_open/vop_close/vop_rdwr/vop_ioctl/vop_select/vop_getattr/vop_setattr/vop_access


vnode数据结构的成员包括:

v_flag: VROOT/VNOMAP/VNOSWAP/VNOMOUNT/VISSWAP

v_count: similar as i_count

v_shlockc: shared lock counter

v_exlockc: number of exclusive locks on the vnode

v_vfsmountedhere: points to the vfs structure of the mounted file-system

v_op: vnode operations associated with this file type

v_vfsp: points to the vfs structure for this file system

v_type: specifies the type of file that the vnode represents VREG/VDIR/VBLK/VCHR/VLINK/VFIFO/VXNAM

v_data: used to reference private data such as a copy of the on-disk inode


可以看到,通过上面的v_vfsmountedherev_vfsp和虚拟文件系统关联了起来。


此外,实现对不同文件系统的统一接口,就需要屏蔽用户态实现io请求的差异。一种避免直接处理或引用user数据结构中的IO相关的信息的方法是把这些信息打包,这就引入了uio_iov的数据结构。 这个数据结构包含下面的成员:

uio_iov:基于user地址和字节数的iovec结构的数组指针;

uio_iovcnt: number of iovec;

uio_offset: 文件内读和写起始的地方

uio_segflg:表明当前请求是来自用户态还是内核态

uio_resid:后面未完成的IO个数


通过上面的uio数据结构,它实现了两个主要的好处:

1. user area access was implemented so that NFS can make a call to the underlying filesystem;

2. readv()/writev() can be implemented


VFS像一个文件系统公共抽象层,或者说是父类也好。 每个挂载的文件系统都对应一个vfs数据结构,该结构的主要成员包括vfs_ops。其中vfs_ops是每个具体的文件系统需要实现的一组操作函数。这些操作包括:

vfs_mount()

vfs_unmount()

vfs_root():返回当前文件系统的根vnode节点,用在路径名解析

vfs_statfs()

vfs_sync()

vfs_fid(): NFS用它来为特殊的vnode构建一个文件句柄

vfs_vget(): NFS用它来把上面返回的文件句柄转换成一个vnode


根据上面的数据结构和操作可以看到:

1. vfs_ops相关的操作只是设计到文件系统层面,不管具体的vnode操作;

2. VFS主要是实现一个抽象类的功能、接口或机制,屏蔽了不同文件的操作上的区别,让应用层看到所有的文件系统操作都是透明的。


讨论完了vfs,再回过头看vnode,它的主要操作如下:

vop_open():针对设备相关的文件操作,一般在vop_lookup返回vnode后调用

vop_close(): 针对设备相关的文件的操作

vop_rdwr():读或写文件,和具体IO相关的信息是通过uio数据结构传递进来的

vop_ioctl():借助针对文件的ioctl操作,函数能够传到设备驱动

vop_select():实现select()系统调用

vop_getattr(): stat()系统调用的实现用这个函数来填充vattr数据结构

vop_setattr():让调用者来设置文件大小、模式、User IDgroup ID、 file times等属性

vop_access():让调用者来检查文件读、写、可执行等权限

vop_lookup():根据指定目录对应的vnode和要查找的文件/设备名, 返回指定目录下和设备名对应的vnode

vop_create():在参数vnode指定的目录下创建一个新文件, 文件属性是通过参数vattr传递进来的。

vop_remove()删除一个目录entry

vop_link()

vop_rename()

vop_mkdir()

vop_rmdir()

vop_readdir()

vop_symlik()

vop_readlink()

上面都是来实现各自对应的系统调用


vop_fsync(): 把内存中任何改动的数据刷到磁盘,实现fsync()系统调用


vop_inacive():当内核中文件系统无关层没有任何模块再使用vnode的时候,文件系统通过这个调用来释放这个vnode;


vop_bmap():向内核VM(Virtual memory subsystem)请求页,以便VM能够把逻辑文件的偏移映射到物理磁盘的偏移


vop_strategy():vop_bmap()之后,VM或者buffer cache 层调用这个函数来读取文件块到内存中。


vop_bread():从指定的vnode对应的文件中读取逻辑块,并且从buffer cache中返回指向这个逻辑块的buffer.


vop_brelse():vop_bread()调用之后,释放buffre.


可以看到vnode是对不同文件系统中各种特殊inode的统一抽象,它屏蔽底层具体文件系统的差异,向文件系统相关的系统调用层提供了统一、公共的函数接口。
















本文转自存储之厨51CTO博客,原文链接:http://blog.51cto.com/xiamachao/1901980 ,如需转载请自行联系原作者





相关文章
|
1月前
|
存储 Linux
btrfs中文件系统扩展属性xattr的实现
介绍Linux中文件系统扩展属性xattr特性的基本概念,btrfs文件系统的基本结构以及对xattr特性的实现方式。
46 1
btrfs中文件系统扩展属性xattr的实现
|
5月前
|
Linux
第八章 NFS文件系统:
第八章 NFS文件系统:
110 1
|
10月前
|
存储 Ubuntu Unix
Linux文件系统(一)文件系统基本概念
Linux文件系统(一)文件系统基本概念
|
Unix Linux 程序员
|
存储 缓存 算法
二十五、文件系统
二十五、文件系统
二十五、文件系统
Ansible 挂载模块mount、格式化磁盘模块filesystem(学习笔记十四)
1、格式化磁盘: ansible all -m filesystem -a "fstype=ext4 dev=/dev/sdb" 2、创建挂载: ansible all -m mount -a 'name=/tmp/app src=/dev/sdb f...
3638 0
|
监控 数据安全/隐私保护 索引
第十八章--Ext2和Ext3文件系统
一、Ext2的一般特征         但在一些情况下,已经在Ext2的索引节点中为这些特性引入新的字段。最重要的一些特点如下:         块片(block fragmentation):系统管理员对磁盘的访问通常选择较大的块,因为计算机应用程序常常处理大文件。
1284 0
|
存储 Linux C++
概述sysfs文件系统【转】
转自:http://blog.csdn.net/npy_lp/article/details/78933292     内核源码:linux-2.6.38.8.tar.bz2     目标平台:ARM体系结构       sysfs是基于内存的文件系统,用于向用户空间导出内核对象并且能对其进行读写。
1226 0