声明:本文为原创
#####请转贴时保留以下内容######
作者:GTT
请提出宝贵意见Mail:mtloveft@hotmail.com
Linux Version:2.6.33
提示:本文是关于file system 实现的介绍!
目录和文件的查找是件很烦琐的事情,早期的linux版本,只有一个minix文件系统,还是很好查找的。
有了VSF之后,各个目录都有可能mount文件系统。这样导致查找的代码很多,而且很难读。而且文件
和目录查找是经常发生的事件,linuxOS首先到dir entry cache里查找,关于目录的查找,新生成时
会同时把dentry加入到cache里。方法实现上也很灵活,运用几个flag来对程序的控制。
总体上来说,对性能上的要求导致程序可读性下降了。
在 VFS 中各种操作, 如建立,删除目录,文件等,首先得进行父目录查找,找到父目录的相关信息,才可以继续操作,如果查找的过程中发现错误,比如父目录不存在,或者当前进程并无相应的权限等等,这种情况系统必然会进行相关处理。
查找一般都是从user_path_parent开始,一步一步查找。如果查找过程很清楚的话,那么fs的各种sys call就很简单了。
定义如下
static int user_path_parent(int dfd, const char __user *path, struct nameidata *nd, char **name)
|
既然是查找,一定要有查找结果,查找结果放到什么地方?就放到一个临时结构里nameidata
变量一般都缩写为nd,这个结构里记录着查找过程中path name, 父目录 path, 根目录。
nameidata 的定义如下
struct nameidata { struct path path; struct qstr last; struct path root; unsigned int flags; int last_type; unsigned depth; //link深度,每次link也++
char * saved_names[MAX_NESTED_LINKS + 1];
/* Intent data */ union { struct open_intent open; } intent; };
|
struct qstr last是放着要查找的path name,它的结构如下,
struct qstr { unsigned int hash; unsigned int len; const unsigned char *name; };
|
它包含一个根据name 算出的hash值。
nameidata 结构中flags的定义如下
#define LOOKUP_FOLLOW 1 #define LOOKUP_DIRECTORY 2 #define LOOKUP_CONTINUE 4 #define LOOKUP_PARENT 16 #define LOOKUP_REVAL 64
|
flags对查找进行指示,LOOKUP_DIRECTORY意思是查找结果必须是目录。
LOOKUP_FOLLOW表示如果查找到的是symbol link ,则顺着symbol link继续查找。
当前进程有计数器current->total_link_count每次查找到一个link 则++
达到特定的值就退出,防止死循环。当发现有符号链接,则depth 也++
再次进入link_path_walk时设置LOOKUP_FOLLOW并清除LOOKUP_CONTINUE 以外的flags
nameidata 结构中last_type的定义如下
/* Type of the last component on LOOKUP_PARENT */ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
|
user_path_parent的处理流程如下
在搜索初始化时path_init,创建 nameidata,之后根据目录名称来设定他的值。
初始化过程在path_init里,如果搜索路径以'/'开头,
nd->root = current->fs->root
nd->path = current->fs->root
如果是AT_FDCWD,既当前工作路径的话
nd->path = current->fs->pwd
而不指定nd->root
nd->path 随着目录节点的深入而不断变化。
阅读(1808) | 评论(1) | 转发(2) |