• 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指针。

  • 相关阅读:
    PHP中laravel拼接原生语句使用find_in_set
    PHP合并某个字段相同的数组,并重组数据算法
    ajax结合php简单的城市三级联动
    简单的qq第三方登录的实现
    laravel设置子域名
    如何在闹钟响时马上起床
    Badminton-playing robot and energy efficiency software
    [阅读技巧] 快速阅读之二 进一步提升阅读资料的速度
    [阅读技巧] 快速阅读入门
    [动态规划] 放置街灯 Uva 10859
  • 原文地址:https://www.cnblogs.com/bettersky/p/7189765.html
Copyright © 2020-2023  润新知