zoukankan      html  css  js  c++  java
  • open调用过程

    1. 首先传到vfs的do_sys_open,在open.c中。

          long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)

    此时,我们只知道open传递过来的一些参数,比如filename,open调用是这样的

         int open(const char *pathname, int flags, mode_t mode);

     因此,只有dfd是新加的,我们先不管他的作用。

    do_sys_open主要做以下事情

    (1) int fd = build_open_flags(flags, mode, &op);//将open传递过来的flags和mode进行整理,赋值给op

       fd = get_unused_fd_flags(flags);//分配一个未使用的fd

        这个fd就是返回给用户open函数的fd。

    (2) tmp = getname(filename); 将文件名做整理,并填充给tmp结构//struct filename *tmp;

    (3) struct file *f = do_filp_open(dfd, tmp, &op); 这个就是实际的打开函数,填充struct file

    (4) fd_install(fd, f); 将fd与 f进行关联。

    2. 上面第(3)步是核心内容。首先我们在这里看struct file结构,/include/linux/fs.h

    里面有三个比较重要的域。

    	struct inode		*f_inode;	/* cached value */
    	const struct file_operations	*f_op;
    	struct address_space	*f_mapping;
    

     我们看do_filp_open如何对他们进行填充。

    (1)首先创建struct nameidata nd; set_nameidata(&nd, dfd, pathname);  

    struct nameidata {
    	struct path	path;
    	struct qstr	last;
    	struct path	root;
    	struct inode	*inode; /* path.dentry.d_inode */
    	unsigned int	flags;
    	unsigned	seq;
    	int		last_type;
    	unsigned	depth;
    	char *saved_names[MAX_NESTED_LINKS + 1];
    
    	/* Intent data */
    	union {
    		struct open_intent open;
    	} intent;
    };

    set_nameidata主要使用参数 pathname 。

    static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
    {
      struct nameidata *old = current->nameidata;
      p->stack = p->internal;
      p->dfd = dfd;
      p->name = name;
      p->total_link_count = old ? old->total_link_count : 0;
      p->saved = old;
      current->nameidata = p;
    }

    struct task_struct首先使用局部指针指向当前进程的nameidata, struct nameidata *old = current->nameidata; 也即是说,每个进程结构包含一个nameidata

    然后只是给nd的total_link_count和pathname赋值。inode并没有管。total_link_count据说是用来防止循环死链的。

    (2) filp = path_openat(&nd, op, flags | LOOKUP_RCU);

    首先是file = get_empty_filp(); 为struct file 分配内存。

     path_init为nd的path和inode赋值,为path->dentry赋值. static int link_path_walk 为nd->last 赋值

    (3)主要的打开操作在 do_last 中。

    link_path_walk 用于一级一级解析文件路径,每一级都调用do_last。 参考:http://alanwu.blog.51cto.com/3652632/1120652

    3. 现在我们来分析 link_path_walk

        函数原型:static int link_path_walk(const char *name, struct nameidata *nd)

        调用方式:link_path_walk(s, nd) ,调用时,s通过 s=path_init(nd, flags)进行了赋值。

    (1)首先,while (*name=='/') name++;假设name是/home/user/xxx,这条语句将name定位到h这个地方。疑惑:这里为什么要用while?这不是会导致路径名可以有多个斜杠?

        如果while后name为null,则直接返回0. 这表明路径是一个目录。

    (2)

    4. 最终,do_last 调用 lookup_open, 调用atmoic_open,调用dir->i_op->atomic_open

          dir是struct inode类型的,定义在/include/linux/fs.h,其中的 struct inode_operations i_op结构含有 atomic_open指针。

  • 相关阅读:
    BestCoder17 1001.Chessboard(hdu 5100) 解题报告
    codeforces 485A.Factory 解题报告
    codeforces 485B Valuable Resources 解题报告
    BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
    codeforces 374A Inna and Pink Pony 解题报告
    codeforces 483B Friends and Presents 解题报告
    BestCoder15 1002.Instruction(hdu 5083) 解题报告
    codeforces 483C.Diverse Permutation 解题报告
    codeforces 483A. Counterexample 解题报告
    NSArray中地内存管理 理解
  • 原文地址:https://www.cnblogs.com/bettersky/p/7189765.html
Copyright © 2011-2022 走看看