Linux文件名到索引节点的查找案例分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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()查找
索引节点