从演进模型的视角来看VFS骨架

VFS是Linux kernel的重要组件,已经有很多书和文章进行论述.

本文从一个略为特别的视角来说明VFS:

通过逐步演进增加模型功能将VFS描述清楚.同时回答why与how.

VFS一个主要的功能是通过path查到到对应文件.
比如"/bin/sh"


VFS1.0


最简模型

VFS是通过树来组织文件的.
1仅dentry就足够建立一棵树.描述文件树.
       "/" 
 |          |
 "bin"    "proc"
向下行走通过dentry->d_subdirs list.
向上行走是通过dentry-d_parent实现.
向上行走是为了支持/bin/../bin/../proc这样的合法,但是略有点怪的路径
当然也有实用价值,就是能在任何点访问任何点的文件.
  

VFS1.1


1.0对于sysfs这样的纯动态生成的树是没有问题的,并且事实上如果内存建立好了这棵树,kernel总是优先使用1.0的内存树,不会去访问磁盘.
但是有2个问题:
1)然而不够持久保持.
如何从磁盘这样的持久保持的数据中重建文件树.
2)如何访问对应的文件内容
kernel通过增加inode来关联磁盘文件,从而实现重建文件树与文件访问.

只要两个数据结构就足够建立namespace到inode的文件树.
1 dentry
2 inode
向下行走时,dentry->d_inode,inode的文件内容指定了下行dentry.
向上行走时,是通过dentry->d_parent实现

1.1模型已经能很好的工作了.猜测windows基本上就是这么干的.windows一个分区只有一个文件系统,很方便.然而UNIX的统一模型.要求在一棵树里面挂载不同的文件系统.这就引入了复杂性.目前的数据结构方案解决不了这个问题.

 

VFS2.0


木有关系,再引入一个vfsmnt,nameidata,同时增强dentry来解决挂载不同文件系统的问题.
其实有一个更简单的方案,就是只增强dentry,每个dentry指向自己文件系统.但是了没有用这个方案.不争论方案优劣.只想说方案不是唯一的.
具体方案:
nameidata指定了vfsmnt与dentry信息.vfsmnt也就是上下文.
向下行走时,Dentry->d_mounted置位说明存在mount挂载,由nameidata找到vfsmnt,由vsfmnt->mnt_child list找到挂载的文件系统.
匹配条件是Dentry==vfsmnt->mnt_mountpoint,切换成挂载点的namidata信息.
由于支持嵌套挂载,vfsmnt->mnt_root,如果vfsmnt->mnt_root->d_mounted置位,继续切换.
采用vfsmnt方案,比更简单的方案强在支持嵌套挂载.另外一个就是分离出了挂载信息.
更强大.Dentry是不知道vfsmnt的任何信息的,仅仅知道是否有mount存在.vfsmnt是隔离于dentry,inode.super_block.
vfsmnt管理vfsmnt层信息
向上是vfsmnt->mnt_parent
向下是vfsmnt->mnt_child & dentry:mnt_mountpoint,mnt_root.
好了,现在有了能任意挂载一棵到另一棵树上的vfs模型.能建立起复杂的文件树了.
注意一点就是vfsmnt代表了一棵树.哪怕是另一棵树的子树.它本身只是一棵独立的树,只有那么点挂载的关系而已.移动一棵树只是修改了挂载关系.原则上说也可以任性的不挂载到别的树上.
 

VFS2.1


Dentry查找加速.Dentry本身就是缓存项.基本思想就是用hash表来加速.
 hash 算法用hash(d_parent ptr+name ),用父dentry的指针地址作为hash key的基是相当聪明.查找当前目录下的子dentry很有效率的.
基本上dentry的d_op绝大部分时间都是NULL,采用默认策略.也就是继承基类.
d_alloc()创建dentryd_op是NULL.
最后比较d_parent== parent, compare name确认是要找的dentry.解决hash冲撞.

猜你喜欢

转载自blog.csdn.net/pcj2007/article/details/81387868
今日推荐