zoukankan      html  css  js  c++  java
  • link_path_walk()分析

     功能:路径名解析
          这是一个基本的路径名解析函数,将一个路径名最终转化为一个dentry;
    成功返回0,并将分量保存在nd中。

    主要数据结构:

    struct qstr { /* 用来存放路径名中当前节点的名,长度 */
    	unsigned int hash;
    	unsigned int len;
    	const unsigned char *name;
    };

    struct nameidata

    struct nameidata {
    	struct path	path; 
    	struct qstr	last;  /* 路径名的最后一个分量 */
    	struct path	root;  /* 已安装文件系统根目录的路径名 */
    	struct inode	*inode; /* path.dentry.d_inode */
    	unsigned int	flags; /* 查找标志 */
    	unsigned	seq;
    	int		last_type; /*最后一个路径名的类型标记 */
    	unsigned	depth; /* 符号链接嵌套的当前界别 */
    	char *saved_names[MAX_NESTED_LINKS + 1]; /* 与嵌套的符号链接关联的路径名数组 */
    
    	/* Intent data */
    	union {
    		struct open_intent open;
    	} intent; /* 单个成员联合体,制定如何访问文件 */
    };

    函数分析:

    static int link_path_walk(const char *name, struct nameidata *nd)
    {
    	struct path next;
    	int err;
    	
    	while (*name=='/') /* 跳过路径名第一个分量前的任何斜杠 */
    		name++;
    	if (!*name) /* 如果剩余路径名为NULL, 则返回0 */
    		return 0;
    
    	/* At this point we know we have a real path component. */
    	for(;;) { /* 把name参数中传递的路径名分解为分量"/"被当做分隔符对于每个分量执行 */
    		unsigned long hash;
    		struct qstr this; /* 用来存放路径名中当前节点的名,长度 */
    		unsigned int c;
    		int type;
    
    		err = may_lookup(nd); /* 检查存放的索引节点的访问模式和运行线程的特权 */
     		if (err)
    			break;
    
    		this.name = name;
    		c = *(const unsigned char *)name;
    
    		hash = init_name_hash();/* hash = 0 */
    		do { /* 将路径名分解为分量,以"/"为分隔符 */
    			name++;
    			hash = partial_name_hash(c, hash);
    			c = *(const unsigned char *)name;
    		} while (c && (c != '/'));
    		this.len = name - (const char *) this.name;
    		this.hash = end_name_hash(hash);
    
    		type = LAST_NORM;
    		if (this.name[0] == '.') switch (this.len) {
    			case 2:
    				if (this.name[1] == '.') {
    					type = LAST_DOTDOT;
    					nd->flags |= LOOKUP_JUMPED;
    				}
    				break; /* 如果是两个圆点则跳出循环,尝试返回父目录 */
    			case 1:/* 如果是单个圆点则继续下个分量 */
    				type = LAST_DOT;
    		}
    		if (likely(type == LAST_NORM)) {/* 说明分两名既不是"." 也不是"..",因此需要在目录项高速缓存中查找 */
    			struct dentry *parent = nd->path.dentry;
    			nd->flags &= ~LOOKUP_JUMPED;
    			if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
    				err = parent->d_op->d_hash(parent, nd->inode,
    							   &this); /* 调用文件系统自定义的d_hash目录项方法,修正hash值 */
    				if (err < 0)
    					break;
    			}
    		}
    
    		/* remove trailing slashes? */
    		if (!c) /* 如果接下来为NULL,则表示为最后一个分量 */
    			goto last_component;
    		while (*++name == '/'); 
    		if (!*name) /* 判断是否还存在分量需解析 */
    			goto last_component;
    		/* 到此说明还有分量需分析 */
    		err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW);/* 将路径名转化为分量 */
    		if (err < 0)
    			return err;
    
    		if (err) { /* 若存在符号链接,且设置了follow_link方法 */
    			err = nested_symlink(&next, nd);/* 解释符号链接 */
    			if (err)
    				return err;
    		}
    		if (can_lookup(nd->inode)) /* 将inode->i_opflags的IOP_LOOKUP位置位,若inode->i_op->lookup定义则为真 */
    			continue;
    		err = -ENOTDIR; 
    		break;
    		/* here ends the main loop */
    
    last_component:
    		nd->last = this;
    		nd->last_type = type;
    		return 0;
    	}
    	terminate_walk(nd); /*  试图返回分量nd所在的目录*/
    	return err;
    }
    基于内核版本linux 3.2
  • 相关阅读:
    day 40 MySQL之视图、触发器、事务、存储过程、函数
    js多元运算
    继承以及Super
    Git工作流指南:Gitflow工作流
    JS中的逻辑运算符&&、||,位运算符|,&
    js的prototype理解
    JS对象—数组总结(创建、属性、方法)
    React-Native中props用法详解
    AJAX中同步和异步的区别和使用场景
    web前端之性能
  • 原文地址:https://www.cnblogs.com/youngerchina/p/5624643.html
Copyright © 2011-2022 走看看