proc文件系统情景分析

情景1:
   int fd=open("/proc");
open->sys_open->do_filp_open
当open的flags包含CREAT标志时->do_path_lookup(dfd, pathname, LOOKUP_PARENT, &nd);
不包含CREAT标志时->path_lookup_open->{
struct file *filp = get_empty_filp();
 nd->intent.open.file = filp;

}->do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);{
if (*name=='/') {
   nd->path = fs->root;
 }
 }-> path_walk(name, nd);->link_path_walk(name, nd);->__link_path_walk(name, nd);->{
last_component:
err = do_lookup(nd, &this, &next); // this代表proc字符串 this.name == "proc",nd->path包含根目录的dentry,和vfsmount信息,next 为待查找到的proc对应的path结构,通过next返回。
//通过下面对do_lookup函数的分析可知,do_lookup函数返回时,next->dentry代表proc文件系统的根目录dentry结构,
next->vfsmount代表proc文件系统的vfsmount
  inode = next.dentry->d_inode;
  if ((lookup_flags & LOOKUP_FOLLOW)
      && inode && inode->i_op && inode->i_op->follow_link) {
   err = do_follow_link(&next, nd);
   if (err)
    goto return_err;
   inode = nd->path.dentry->d_inode;
  } else
   path_to_nameidata(&next, nd);->{
path_to_nameidata(struct path *path, struct nameidata *nd)
if (nd->path.mnt != path->mnt)
  mntput(nd->path.mnt);
 nd->path.mnt = path->mnt;
 nd->path.dentry = path->dentry;
}
  err = -ENOENT;
  if (!inode)
   break;
  if (lookup_flags & LOOKUP_DIRECTORY) {
   err = -ENOTDIR;
   if (!inode->i_op || !inode->i_op->lookup)
    break;
  }
  goto return_base;
return_base:
  return 0; //返回到link_path_walk,一路返回到do_filp_open(),下面再来看下do_filp_open相关部分代码
}
do_filp_open(){
 if (!(flag & O_CREAT)) {
  error = path_lookup_open(dfd, pathname, lookup_flags(flag),
      &nd, flag);
  if (error)
   return ERR_PTR(error);
  goto ok;
 }
ok:filp = nameidata_to_filp(&nd, open_flag);
return filp;
}

struct file *nameidata_to_filp(struct nameidata *nd, int flags)
{
 struct file *filp;

 /* Pick up the filp from the open intent */
 filp = nd->intent.open.file; //这个file是我们在path_lookup_open中分配的
 /* Has the filesystem initialised the file for us? */
 if (filp->f_path.dentry == NULL)
  filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp,
         NULL);
 -> static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
     int flags, struct file *f,
     int (*open)(struct inode *, struct file *)){
inode = dentry->d_inode;
f->f_path.dentry = dentry;
//在这里将为打开/proc而分配的file结构与查找到的dentry结构挂钩
 f->f_path.mnt = mnt;
f->f_op = fops_get(inode->i_fop);
//将inode->i_fop复制到file结构体f_op字段
}
 else
  path_put(&nd->path);
 return filp;
}

static int do_lookup(struct nameidata *nd, struct qstr *name,
       struct path *path)
//// name代表proc字符串 name.name == "proc",nd->path包含根目录的dentry,和vfsmount信息,path为待查找到的proc对应的path结构,通过此指针返回。
{
 struct vfsmount *mnt = nd->path.mnt;
 struct dentry *dentry = __d_lookup(nd->path.dentry, name);
done:
 path->mnt = mnt;
 path->dentry = dentry;
 __follow_mount(path); ->{
   struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry);
   path->mnt = mounted;
  path->dentry = dget(mounted->mnt_root);
//这里path代表了proc文件系统的根目录

}
 return 0; //返回到__link_path_walk继续分析
}
情景2 ls /proc
readdir("/proc") -> sys_getdents64()->vfs_readdir(struct file *file){
//file结构代表 /proc,file->f_path.dentry已指向/proc dentry结构 file->f_op已指向/proc inode节点的file_operations结构
(file->f_op->readdir(file, buf, filler); --> static int proc_root_readdir(struct file * filp,  void * dirent, filldir_t filldir)
{
//由于这个函数比较大,放在下面分析
   }
}
在proc文件系统安装注册过程中,/proc inode的file_operations定义为:
/*
 * This is the root "inode" in the /proc tree..
 */
struct proc_dir_entry proc_root = {
 .low_ino = PROC_ROOT_INO,
 .namelen = 5,
 .name  = "/proc",
 .mode  = S_IFDIR | S_IRUGO | S_IXUGO,
 .nlink  = 2,
 .count  = ATOMIC_INIT(1),
 .proc_iops = &proc_root_inode_operations,
 .proc_fops = &proc_root_operations,
 .parent  = &proc_root,
};
/*
 * The root /proc directory is special, as it has the
 * <pid> directories. Thus we don't use the generic
 * directory handling functions for that..
 */
static const struct file_operations proc_root_operations = {
 .read   = generic_read_dir,
 .readdir  = proc_root_readdir,
};

static int proc_root_readdir(struct file * filp,
 void * dirent, filldir_t filldir)
{
 unsigned int nr = filp->f_pos;
 int ret;

 lock_kernel();

 if (nr < FIRST_PROCESS_ENTRY) {
  int error = proc_readdir(filp, dirent, filldir);
  if (error <= 0) {
   unlock_kernel();
   return error;
  }
  filp->f_pos = FIRST_PROCESS_ENTRY;
 }
 unlock_kernel();

 ret = proc_pid_readdir(filp, dirent, filldir);
 return ret;
}

posted on 2010-12-17 10:28 lstar 阅读(228) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2020年2月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
1234567

统计

常用链接

留言簿

文章档案

搜索

最新评论