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

网友投稿 992 2022-09-21

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

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

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

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

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

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

3.支持NFS 服务器端

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

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

新设计的主要架构如下:

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

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_vfsmountedhere和v_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 ID、group 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的统一抽象,它屏蔽底层具体文件系统的差异,向文件系统相关的系统调用层提供了统一、公共的函数接口。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:编写sed脚本
下一篇:房子小程序开发(房产小程序开发选哪家)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~