文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>版本2.4.16下path_init和path_walk,link_path_w..

版本2.4.16下path_init和path_walk,link_path_w..

时间:2010-08-16  来源:sunseven1245yahoocn

原文地址:http://www.linuxforum.net/forum/printthread.php?Cat=&Board=linuxK&main=261164&type=thread

这两个函数可以说是一对搭档,联合起来根据一段路径名找到对应的dentry,如果内存中没有会建立,当然有了dentry就少不了inode。顾名思义,path-init为查找作准备工作,path_walk真正上路查找。以下的分析略去了很多繁枝末节。
1. path_init
原型:int path_init(const char *name, unsigned int flags, struct nameidata *nd)。
入口参数:name指明了要查找的路径,如绝对路径“/usr/local/info.txt”,相对路径“ ./info.txt”,
或只有路径“/usr/local”。
Nd目的是为了回传,重点是它的成员dentry。
返回值:0表示OK。更重要的是,当函数返回时,nd->dentry为搜索name的起点。
分析:
这个函数比较简单,是一个给nd赋值的过程。
nd->last_type = LAST_ROOT;
nd->flags = flags;
if (*name=='/')
return walk_init_root(name,nd);
read_lock(&current->fs->lock);
nd->mnt = mntget(current->fs->pwdmnt);
nd->dentry = dget(current->fs->pwd);
根据当前进程和路径的相对或绝对给nd赋值,没什么好讲的。
2. path_walk
原型:int path_walk(const char * name, struct nameidata *nd)
入口参数:name和path_init具有相同的值。
nd也和path_init一样,此时nd->dentry已经指向了搜索的起点。
返回值:0表示OK。更重要的是,当函数返回时,nd->dentry为name对应的dentry。
分析:此函数调用了link_path_walk完成了所有的功能。
3. link_path_walk
原型:int link_path_walk(const char * name, struct nameidata *nd)
入口参数:name和path_walk具有相同的值。
nd也和path_walk一样,此时nd->dentry已经指向了搜索的起点。
返回值:0表示OK。更重要的是,当函数返回时,nd->dentry为name对应的dentry。
分析:我觉得这个函数相当重要,就如源代码注释的那样,是整个NFS的名字解析函数,其实也是NFS得以构筑的函数。这里作一重点分析。
这里先作一个综述。该函数采用一个for循环,对name路径根据目录的层次,一层一层推进,直到终点或失败。在推进的过程中,一步步建立了目录树的dentry和对应的inode。

举例如下:
初始条件:name为”./step1/step2/info.txt”。
nd->dentry为“./”对应的dentry。
第一步:根据nd->dentry(和“./”对应)和“step1”找到或建立与“./step1”对应的dentry。
第二步:根据nd->dentry(和“./step1”对应)和“step2”找到或建立与“./step1/step2”对应的dentry。
第三步:根据nd->dentry(和“./step1/step2”对应)和“info.txt”找到或建立与“./step1/step2/info.txt”对应的dentry。
第四步:返回。

源代码分析如下:
int link_path_walk(const char * name, struct nameidata *nd)
{
struct dentry *dentry;
struct inode *inode;
int err;
unsigned int lookup_flags = nd->flags;

while (*name=='/')
name++; //多个/视作一个
if (!*name)
goto return_base; //本目录,直接返回OK

inode = nd->dentry->d_inode; //准备循环,此时的inode一定在内存
if (current->link_count)
lookup_flags = LOOKUP_FOLLOW;

/* At this point we know we have a real path component. */
for(;;) {
unsigned long hash;
struct qstr this;
unsigned int c;

err = permission(inode, MAY_EXEC);
dentry = ERR_PTR(err);
if (err)
break;

this.name = name;
c = *(const unsigned char *)name;

hash = init_name_hash();
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); //对下一级目录或文件求hash值

/* remove trailing slashes? */
if (!c)
goto last_component; //最后一次
while (*++name == '/'); //对路径中间的多个/也视作一个
if (!*name)
goto last_with_slashes; //最后一次,不过为目录

/*
* "." and ".." are special - ".." especially so because it has
* to be able to know about the current root directory and
* parent relationships.
*/
if (this.name[0] == '.') switch (this.len) {
default:
break;
case 2:
if (this.name[1] != '.')
break;
follow_dotdot(nd);
inode = nd->dentry->d_inode;
/* fallthrough */
case 1:
continue;
} //处理.和 ..,由此可知.和..可以在路径中间出现
/*
* See if the low-level filesystem might want
* to use its own hash..
*/
if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
err = nd->dentry->d_op->d_hash(nd->dentry, &this);
if (err < 0)
break;
}
/* This does the actual lookups.. */
dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
//在目录缓存里查找,其实调用了d_lookup(VFS函数)。
if (!dentry) {
dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
//这里较为重要,因为它创建dentry并调用了与文件系统相关的lookup函数,如ext2_lookup等,其调用是通过nd->dentry->inode->lookup到达的。该lookup函数创建VFS inode,并赋予相应的值。
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
break;
}
/* Check mountpoints.. */
while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
;
//对安装点推进
err = -ENOENT;
inode = dentry->d_inode;
if (!inode)
goto out_dput;
err = -ENOTDIR;
if (!inode->i_op)
goto out_dput;

if (inode->i_op->follow_link) {
err = do_follow_link(dentry, nd);
dput(dentry);
if (err)
goto return_err;
err = -ENOENT;
inode = nd->dentry->d_inode;
if (!inode)
break;
err = -ENOTDIR;
if (!inode->i_op)
break;
} else {
dput(nd->dentry);
nd->dentry = dentry;
}
err = -ENOTDIR;
if (!inode->i_op->lookup)
break;
continue;
/* here ends the main loop */

last_with_slashes:
lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
last_component:
if (lookup_flags & LOOKUP_PARENT)
goto lookup_parent;
if (this.name[0] == '.') switch (this.len) {
default:
break;
case 2:
if (this.name[1] != '.')
break;
follow_dotdot(nd);
inode = nd->dentry->d_inode;
/* fallthrough */
case 1:
goto return_base;
}
if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
err = nd->dentry->d_op->d_hash(nd->dentry, &this);
if (err < 0)
break;
}
dentry = cached_lookup(nd->dentry, &this, 0);
if (!dentry) {
dentry = real_lookup(nd->dentry, &this, 0);
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
break;
}
while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))
;
inode = dentry->d_inode;
if ((lookup_flags & LOOKUP_FOLLOW)
&& inode && inode->i_op && inode->i_op->follow_link) {
err = do_follow_link(dentry, nd);
dput(dentry);
if (err)
goto return_err;
inode = nd->dentry->d_inode;
} else {
dput(nd->dentry);
nd->dentry = dentry;
}
//对连接的处理
err = -ENOENT;
if (!inode)
goto no_inode;
if (lookup_flags & LOOKUP_DIRECTORY) {
err = -ENOTDIR;
if (!inode->i_op || !inode->i_op->lookup)
break;
}
goto return_base;
no_inode:
err = -ENOENT;
if (lookup_flags & (LOOKUP_POSITIVE|LOOKUP_DIRECTORY))
break;
goto return_base;
lookup_parent:
nd->last = this;
nd->last_type = LAST_NORM;
if (this.name[0] != '.')
goto return_base;
if (this.len == 1)
nd->last_type = LAST_DOT;
else if (this.len == 2 && this.name[1] == '.')
nd->last_type = LAST_DOTDOT;
return_base:
return 0;
out_dput:
dput(dentry);
break;
}
path_release(nd);
return_err:
return err;
}

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载