• kernel 文件系统挂载流程分析【转】


    转自:https://blog.csdn.net/wuu1010/article/details/94332319

    1. mount系统调用

    1.1. sys_mount

    sys_mount主要将系统调用的参数dev_name、dir_name、type、flags、data从用户空间拷贝到内核空间,然后调用do_mount函数

    sys_mount
    	copy_mount_string
    	copy_mount_options
    	do_mount
    		user_path(dirname, &path) -> path_lookupat ==> 复杂的过程,找到目录对应的挂载描述符合dentry实例
    		do_remount
    		do_loopback
    		do_change_type
    		do_move_mount
    		do_new_mount	// 构建虚拟挂载点vsfmount,检查设置namespace
    			get_fs_type // 根据文件系统类型的命长找到file_system_type实例
    			vfs_kernel_mount    // 调用具体文件系统的mount,并将返回的root dentry与分配的vfsmount挂接
    				alloc_vfsmnt    // 分配挂载描述符
    				mount_fs
    					type->mount // 调用具体文件系统的mount,返回root dentry
    					设置vfsmount结构内容
    				把挂载描述符添加到长几块的挂载实例链表中
    		do_add_mount
    			graft_tree
    				attach_recursive_mnt
    					commit_tree
    						__attach_mnt
    							把挂载描述符加入散列表
    							把挂载描述符加入父亲的孩子列表
    

    mount

    SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
    		char __user *, type, unsigned long, flags, void __user *, data)
    {
    	int ret;
    	char *kernel_type;
    	char *kernel_dev;
    	void *options;
    
    	kernel_type = copy_mount_string(type);
    	ret = PTR_ERR(kernel_type);
    	if (IS_ERR(kernel_type))
    		goto out_type;
    
    	kernel_dev = copy_mount_string(dev_name);
    	ret = PTR_ERR(kernel_dev);
    	if (IS_ERR(kernel_dev))
    		goto out_dev;
    
    	options = copy_mount_options(data);
    	ret = PTR_ERR(options);
    	if (IS_ERR(options))
    		goto out_data;
    
    	ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
    
    	kfree(options);
    out_data:
    	kfree(kernel_dev);
    out_dev:
    	kfree(kernel_type);
    out_type:
    	return ret;
    }
    

    do_mount

    1.2. ext4文件系统的mount

    mount_fs中通过下边语句调用特定文件系统的mount函数。

    root = type->mount(type, flags, name, data);
    
    • 1

    ext4_fs_type

    static struct file_system_type ext4_fs_type = {
    	.owner		= THIS_MODULE,
    	.name		= "ext4",
    	.mount		= ext4_mount,
    	.kill_sb	= kill_block_super,
    	.fs_flags	= FS_REQUIRES_DEV,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ext4_mount

    static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
    		       const char *dev_name, void *data)
    {
    	return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    mount_bdev是针对块设备挂载时使用的函数,此外还有mount_nodev, mount_single等函数,分别用于不同的挂载情况。
    mount_bdev函数的主要逻辑如下:

    1. blkdev_get_by_path根据设备名得到block_device结构
    2. sget得到已经存在或者新分配的super_block结构
    3. 如果是已经存在的sb,就释放第一步得到的bdev结构
    4. 如果是新的sb,就调用文件系统个别实现的fill_super函数继续处理新的sb,并创建根inode, dentry
    5. 返回得到的s_root
    6. fill_super函数将完成mount接下来重要的工作

    1.4. ext4_fill_super

    在磁盘挂载的时候文件系统需要从磁盘中读取超级块来填充内存中的结构,EXT4文件系统超级块的填充是由函数ext4_fill_super()来完成的。在EXT4文件系统中,磁盘上的超级块结构是与结构体structext4_super_block的定义是一致的,大小是1K,即1024个字节。顺便提下,EXT3文件系统超级块在磁盘上的大小也是1024个字节,EXT4扩展了EXT3的定义,EXT3只是占了1024个字节,有些字节没有定义,在EXT4中重新定义了,总的大小没有改变。

    在挂载文件系统的时候,读取磁盘上ext4_super_block结构的值,填充内存中ext4_sb_info的结构。

    2. 挂载根文件系统

    start_kernel
        vfs_caches_init
            mnt_init
                init_rootfs     // 注册rootfs文件系统
                init_mount_tree // 挂载rootfs文件系统
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.1. init_rootfs

    init_rootfs注册rootfs文件系统

    static struct file_system_type rootfs_fs_type = {
    	.name		= "rootfs",
    	.mount		= rootfs_mount,
    	.kill_sb	= kill_litter_super,
    };
    
    int __init init_rootfs(void)
    {
    	int err = register_filesystem(&rootfs_fs_type);
    
    	if (err)
    		return err;
    
    	if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] &&
    		(!root_fs_names || strstr(root_fs_names, "tmpfs"))) {
    		err = shmem_init();
    		is_tmpfs = true;
    	} else {
    		err = init_ramfs_fs();
    	}
    
    	if (err)
    		unregister_filesystem(&rootfs_fs_type);
    
    	return err;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2.2. init_mount_tree

    init_mount_tree

    static void __init init_mount_tree(void)
    {
    	struct vfsmount *mnt;
    	struct mnt_namespace *ns;
    	struct path root;
    	struct file_system_type *type;
    
    	type = get_fs_type("rootfs");
    	if (!type)
    		panic("Can't find rootfs type");
    	mnt = vfs_kern_mount(type, 0, "rootfs", NULL);  // 挂载rootfs文件系统
    	put_filesystem(type);
    	if (IS_ERR(mnt))
    		panic("Can't create rootfs");
    
    	ns = create_mnt_ns(mnt);                        // 创建第一个挂载命名空间
    	if (IS_ERR(ns))
    		panic("Can't allocate initial namespace");
    
    	init_task.nsproxy->mnt_ns = ns;                 // 设置0号线程的挂载命名工具
    	get_mnt_ns(ns);
    
    	root.mnt = mnt;
    	root.dentry = mnt->mnt_root;
    	mnt->mnt_flags |= MNT_LOCKED;
    
    	set_fs_pwd(current->fs, &root);                 // 把0号线程的当前工作目录设置为rootfs文件系统的根目录
    	set_fs_root(current->fs, &root);                // 把0号线程的根目录设置为rootfs文件系统的根目录
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    3. 参考资料

    1. Linux内核-文件系统-挂载流程分析
    2. Linux内核深度解析-第6章 文件系统
    3. mount过程分析之五(mount_bdev->fill_super)
    4. EXT4文件系统之ext4_fill_super()
    5. EXT4文件系统笔记之ext4_fill_super
    【作者】张昺华
    【大饼教你学系列】https://edu.csdn.net/course/detail/10393
    【新浪微博】 张昺华--sky
    【twitter】 @sky2030_
    【微信公众号】 张昺华
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    接口和抽象类的区别
    MFC之ListCtrl动态添加按钮
    C++类间转换之dynamic_cast
    字符串提取
    C++实现快速排序
    MFC中CListCtrl类依靠CImageList贴图并显示不同图像
    北工大耿丹学院16级计科院3班C语言课程助教学期总结
    C语言课程2——我们交流的工具:Coding.net
    salt-minion安装脚本
    zabbix邮件报警脚本
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/13737377.html
Copyright © 2020-2023  润新知