zoukankan      html  css  js  c++  java
  • linux文件系统初探--Day2(1)

    每个mount过程都会存在一个超级块与之对应,超级块中包含了相关的信息。在写代码之前,首先搞清楚mount过程是很有必要的。

    以下部分参考《深入Linux内核架构》第八章。

    vfsmount和super_block结构初步

    在day1中,我们完成了文件系统的注册,也就是说我们将samplefs的信息通知内核,让内核知道有这么个东西,所以在注册过程中只需要向file_systems链表添加一个对象就可以。但是mount过程相对来说比较复杂,下面我们详细了解。

    Unix采用了一种单一的文件系统结构,新的文件系统可以嵌套其中。文件系统mount的目录叫做装载点,在将文件系统mount到一个目录时,装载点的内容被替换为即将装载的文件系统的相对根目录的位置。每个装载的文件系统都对应了一个vfsmount实例。

    struct vfsmount {
          struct dentry *mnt_root;
          struct super_block *mnt_sb;
          int mnt_flags;
    }
    

    mnt_root中保存了当前文件系统根目录的dentry,mnt_sb中保存了当前文件系统对应的超级块。在早期内核中,vfsmount中还存在很多链表元素,目前这些成员都被转移到struct mount中,暂不对其进行更深入的分析。

    在装载文件系统前,首先需要创建超级块,之后对超级块进行读取,装载工作才算正式开始,struct super_block的结构是这样的:

    struct super_block {
    
    	[...snipped...]
    
    	unsigned char		s_blocksize_bits;
    	unsigned long		s_blocksize;
    	loff_t			s_maxbytes;	/* Max file size */
    	struct file_system_type	*s_type;
    	const struct super_operations	*s_op;
    
    	[...snipped...]
    
    	unsigned long		s_magic;
    	struct dentry		*s_root;
    
    	[...snipped...]
    
    	void 			*s_fs_info;	/* Filesystem private info */
    
    	[...snipped...]
    
    	/* Granularity of c/m/atime in ns.
    	   Cannot be worse than a second */
    	u32		   s_time_gran;
    
    	[...snipped...]
    };
    

    s_blocksize 和 s_blocksize_bits指定了文件系统的块长度。
    s_type指向file_syetem_type的实例,保存了与文件系统有关的一般类型的信息。
    s_root将超级块与全局根目录的dentry关联起来,而根目录的dentry又可以指向根目录的inode。一般用s_root检查文件系统是否已经装载,如果是NULL,则该文件系统只在内核内部可见,否则在用户空间中可见。
    s_fs_info指向文件系统的私有信息。
    s_op指向一个包含了函数指针的结构,提供了处理超级块的一般接口。具体的struct super_operations暂时不做介绍。

    mount系统调用

    mount系统调用在fs/namespace.c中实现:

    SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
    		char __user *, type, unsigned long, flags, void __user *, data)
    {
    	return ksys_mount(dev_name, dir_name, type, flags, data);
    }
    

    因此在5.4.89内核中,mount一个新文件系统的路径如下:

    mount -> ksys_mount -> do_mount -> do_new_mount -> do_new_mount_fc -> vfs_create_mount, do_add_mount
    

    我们发现在5.4.89内核中,在do_new_mount过程中,调用do_new_mount_fc,发现使用了一个fs_context新结构。

    struct fs_context {
    	const struct fs_context_operations *ops;
    	struct mutex		uapi_mutex;	/* Userspace access mutex */
    	struct file_system_type	*fs_type;
    	void			*fs_private;	/* The filesystem's context */
    	void			*sget_key;
    	struct dentry		*root;		/* The root and superblock */
    	struct user_namespace	*user_ns;	/* The user namespace for this mount */
    	struct net		*net_ns;	/* The network namespace for this mount */
    	const struct cred	*cred;		/* The mounter's credentials */
    	struct fc_log		*log;		/* Logging buffer */
    	const char		*source;	/* The source name (eg. dev path) */
    	void			*security;	/* Linux S&M options */
    	void			*s_fs_info;	/* Proposed s_fs_info */
    	unsigned int		sb_flags;	/* Proposed superblock flags (SB_*) */
    	unsigned int		sb_flags_mask;	/* Superblock flags that were changed */
    	unsigned int		s_iflags;	/* OR'd with sb->s_iflags */
    	unsigned int		lsm_flags;	/* Information flags from the fs to the LSM */
    	enum fs_context_purpose	purpose:8;
    	enum fs_context_phase	phase:8;	/* The phase the context is in */
    	bool			need_free:1;	/* Need to call ops->free() */
    	bool			global:1;	/* Goes into &init_user_ns */
    };
    

    我们发现,vfs_create_mount中原来回调fill_super函数的位置现在变成了一个dget(fc->root),所以我个人觉得调用fill_super的位置应该在vfs_get_tree中,但是目前这个函数的具体实现并未找到,明天再说。。。

    写了一下午,发现自己还完全没有追内核的能力。。。只能看看大佬的文章学习了。

    参考资料

    Linux中的VFS实现 [二]
    mount系统调用初探

    明天把上面这两篇专栏系统看一看。

  • 相关阅读:
    springmvc log4j 配置
    intellij idea maven springmvc 环境搭建
    spring,property not found on type
    intellij idea maven 工程生成可执行的jar
    device eth0 does not seem to be present, delaying initialization
    macos ssh host配置及免密登陆
    centos7 搭建 docker 环境
    通过rest接口获取自增id (twitter snowflake算法)
    微信小程序开发体验
    gitbook 制作 beego 参考手册
  • 原文地址:https://www.cnblogs.com/LuoboLiam/p/14293298.html
Copyright © 2011-2022 走看看