Linux文件名到索引节点的查找案例分析

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

文件名到索引节点的查找

一,总体过程:

__user_walk()首先调用path_init()查找文件绝对路径名或相对路

径名的搜索起点的根目录或当前目录,接着调用path_walk()在目

录项内得到对应的索引节点。

二,代码分析,详细原理:

/*参数:name: 指向在用户空间中的路径名

flags: 用来指示怎样寻找目标的标志位

nd: nameidata结构用于在路径查找过程中记录中间信息和查找结果struct nameidata{

struct dentry *dentry;

struct vfsmount *mnt;

struct qstr last;

unsigned int flags;

int last_type;

};

*/

int __user_walk(const char *name, unsigned flags, struct nameidata *nd) {

char *tmp;

int err;

tmp = getname(name);/* 通过getname()在系统空间中分配一个页面,

从用户空间把文件名name复制到这个页面中,

并把分配的页面的路径名赋给tmp */ err = PTR_ERR(tmp); /* 强制转换tmp为long,用来判断函数的返回值

是否是一个有效的指针,指针有三种情况,一种是有

效指针,一种是NULL,空指针,一种是错误指针,或

者说无效指针,就是指其已经到达了最后一个page.

内核空间最高地址0xffffffff,那么最后一个page

就是指的0xfffff000~0xffffffff(4k一个page) */ if (!IS_ERR(tmp)) {/* getname()返回有可能是一个分配的页面的首地址:

通过PTR_ERR()将这个指针类型的地址转化为一个

整型,再通过IS_ERR()判断是否是一个有效的页面首

地址;若getname()返回时错误码情况,ENOMEM定义

值是12,经过ERR_PTR(-ENOMEM)返回成了指针类

型,指向0xFFFFFFF4,指向虚拟内核空间的top4KB 空

间,通过IS_ERR()判断返回的是false */

err = 0;

if (path_init(tmp, flags, nd))/* 若返回1,则完成对路径的搜索工作,

即对nameidata结构的初始化完成,此时

nameidata结构中的指针dentry指向路径

搜索的起点*/

err = path_walk(tmp, nd); /* 通过path_walk()顺着路径名的指引进

行搜索,找到索引节点*/

putname(tmp); /* 通过putname()释放之前动态分配的空间*/ }

return err;

}

int path_init(const char *name, unsigned int flags, struct nameidata *nd)

{

nd->last_type = LAST_ROOT; /* 将nameeidata结构中的last_type字段

设置成LAST_ROOT,在搜索的过程中,

这个字段的值会随着路径名的当前搜索结

果而变。例如当成功地找到目标文件,

会变成LAST_NORM;当最后停留在一个“.”

上,则变成LAST_DOT */

nd->flags = flags; /* 标志位*/

if (*name=='/') /* 路径名若是以“/”开头,则说明给出的是绝

对路径,需要通过walk_init_root()从根节点

开始查找*/

return walk_init_root(name,nd); /* “替换”根目录,

完成工作:当前进程的进程控制块中有

个指针fs指向一个fs_struct结构,

其中有个指针pwd(即current->fs->pwd

指向“当前工作目录”的dentry,将

nameidata中的指针dentry指向这个

dentry, 同理nameidata中的指针mnt

指向这个vfsmount */

/* 此时已经是(或转换成)相对路径,要从当前进程环境中取出当前目录的dentry, 及mnt */

read_lock(¤t->fs->lock); /* 上锁状态*/

nd->mnt = mntget(current->fs->pwdmnt);/* 与下面的dentry操作类似*/ nd->dentry = dget(current->fs->pwd); /* 调用dget()增添共享计数(因为

dentry多了一个“用户”)*/ read_unlock(¤t->fs->lock);/* 解锁状态*/

return 1;

}

三,流程图:

调用getname()分

配页面

强制转换getname()

返回值

调用path_init()搜

索根目录成功?

调用path_walk()查找

索引节点

相关文档
最新文档