分类: LINUX
2010-11-24 18:10:50
我们知道, vfsmount A、B、C 之间形成了一种父子关系,为什么不根据 A 来找到 B ,根据 B 找到 C 了?
这是因为一个文件系统可能同时被安装到不同的“安装点”上。
假设把 /dev/sda1 同时安装到 /mnt/win 和 /mnt/linux 下
现在 /mnt/win/dir1 和 /mnt/linux/dir1 对应的是同一个 dentry!!!
然后,又把 /dev/sda2 分别安装到 /mnt/win/dir1 和 /mnt/linux/dir1 下
现在, vfsmount 与 dentry 之间的关系大致如下。可以看到:
1、 现在有四个 vfsmount A, B, C, D
2、 A 和B对应着不同的安装点 ‘win’ 和 ‘linux’,但是都指向 /dev/sda1 根目录的 dentry
3、 C 和D 对应着这相同的安装点 ‘dir1’,也都指向 /dev/sda2 根目录的 dentry
4、 C 是 A 的 child, A是 C 的 parent
5、 D 是 B 的 child, B 是 D 的 parent
在搜索初始化时,创建 nameidata,其中 mnt 指向 current->fs->rootmnt,dentry 指向 current->fs->root
dentry 随着目录节点的深入而不断变化;
而 mnt 则在每进入一个新的文件系统后发生变化
以寻找 /mnt/win/dir1/abc 为例
开始的时候, mnt 指向 vfsmount A,dentry 指向根设备的根目录
随后,dentry 先后指向 ‘mnt’ 和 ‘win’ 对应的 dentry
然后当寻找到 vfsmount B 后,mnt 指向了它,而 dentry 则指向了 /dev/sda1 根目录的 dentry
有了这个结构,上一节的问题就可以得到解决了:
在寻找 /mnt/win/dir1/abc 的过程中,首先找到 A,接下来在要决定选 C 还是 D,因为是从 A 搜索下来的, C 是 A 的 child,因此选择 C 而不是 D;同样,如果是寻找 /mnt/linux/dir1/abc,则会依次选择 B 和D。这就是为什么 nameidata 中要带着一个 vfsmount 的原因。一个文件每被打开一次,就对应着一个 file 结构。
我们知道,每个文件对应着一个 dentry 和 inode,每打开一个文件,只要找到对应的 dentry 和 inode 不就可以了么?为什么还要引入这个 file 结构?
这是因为一个文件可以被同时打开多次,每次打开的方式也可以不一样。
而dentry 和 inode 只能描述一个物理的文件,无法描述“打开”这个概念。
因此有必要引入 file 结构,来描述一个“被打开的文件”。每打开一个文件,就创建一个 file 结构。
file 结构中包含以下信息:
打开这个文件的进程的 uid,pid
打开的方式
读写的方式
当前在文件中的位置
实际上,打开文件的过程正是建立file, dentry, inode 之间的关联的过程。文件一旦被打开,数据结构之间的关系已经建立,后面对文件的读写以及其它操作都变得很简单。就是根据 fd 找到 file 结构,然后找到 dentry 和 inode,最后通过 inode->i_fop 中对应的函数进行具体的读写等操作即可。