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系统调用初探

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

  • 相关阅读:
    进程、线程和协程的区别(转)
    IO多路复用机制(转)
    防火墙及其功能(转)
    TCP连接的建立和终止。
    TCP和UDP细致刻画,区别。
    typename T和class T区别与联系
    TCP UDP的详解开始 ----UNIX网络编程
    关于UNIX网络编程的的OSI,1.7章的总结
    UNIX网络编程daytime服务端和客户端的实现过程
    linux shell脚本执行错误:bad substitution
  • 原文地址:https://www.cnblogs.com/LuoboLiam/p/14293298.html
Copyright © 2011-2022 走看看