Linux虚拟文件系统--文件路径名的解析(2)--回退父目录


上文介绍了解析文件路径名的一个通体的过程,这里再把其中的一些细节拿出来进行分析。首先对于文件名的特点,可以分为三类:普通文件名,'.'和'..',对于'.'的处理很简单,因为它表示当前目录,因此直接通过continue进入下一轮查找即可,对于'..',也就是退回到父目录,本身也不是一件难事,但是这里要考虑到几个特殊情况,先看看内核处理'..'的方法:

相关阅读:Linux虚拟文件系统--文件路径名的解析(2)--回退父目录

static __always_inline void follow_dotdot(struct nameidata *nd) 

    set_root(nd); 
 
    while(1) { 
        struct vfsmount *parent; 
        struct dentry *old = nd->path.dentry; 
 
        /*如果当前所处的目录即为根目录则break*/ 
        if (nd->path.dentry == nd->root.dentry && 
            nd->path.mnt == nd->root.mnt) { 
            break; 
        } 
        spin_lock(&dcache_lock); 
 
        //如果当前所处的目录不为当前路径所属文件系统的根目录,也就是说可以直接向上退一级 
        if (nd->path.dentry != nd->path.mnt->mnt_root) { 
            nd->path.dentry = dget(nd->path.dentry->d_parent);//当前的目录退到上一级 
            spin_unlock(&dcache_lock); 
            dput(old); 
            break; 
        } 
 
        /*下面的情况对应于当前所处的目录为文件系统的根目录*/ 
        spin_unlock(&dcache_lock); 
        spin_lock(&vfsmount_lock); 
        parent = nd->path.mnt->mnt_parent;//取父文件系统 
        if (parent == nd->path.mnt) {//父文件系统即为本身,则表明没有父文件系统,直接break 
            spin_unlock(&vfsmount_lock); 
            break; 
        } 
        mntget(parent);//增加父文件系统的引用计数 
        nd->path.dentry = dget(nd->path.mnt->mnt_mountpoint);//取当前文件系统的挂载点,这样就退回到了父文件系统 
        spin_unlock(&vfsmount_lock); 
        dput(old); 
        mntput(nd->path.mnt); 
        nd->path.mnt = parent;//设置当前路径的mnt为父文件系统 
    } 
    /*一般情况下,前面的操作可以保证返回到上级目录,但是有一种情况就是
      当前目录的上级目录有可能还挂载了其他的文件系统,这样会隐藏之前的文件系统,
      follow_mount()用来处理这种情况*/ 
    follow_mount(&nd->path); 

while循环里面的路径可以分为三种:

1.当前目录为nd中已经预设好的根目录,也就是说无法再向上退一层了,这种情况直接break

2.当前目录不为所属文件系统的根目录,这种情况是最常见的,可以向上退一层

3.当前目录为所属文件系统的挂载点,这种情况下,后退一层的话则会进入到父文件系统中,所以先要做一个文件系统的交换,再通过while(1)循环回到前面两种情况

  • 1
  • 2
  • 下一页

相关内容