zoukankan      html  css  js  c++  java
  • linux文件系统初始化过程(2)---挂载rootfs文件系统【转】

    转自:https://blog.csdn.net/luomoweilan/article/details/17894473?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

    一、目的

        本文主要讲述linux3.10文件系统初始化过程的第一阶段:挂载rootfs文件系统

        rootfs是基于内存的文件系统,所有操作都在内存中完成;也没有实际的存储设备,所以不需要设备驱动程序的参与。基于以上原因,linux在启动阶段使用rootfs文件系统,当磁盘驱动程序和磁盘文件系统成功加载后,linux系统会将系统根目录从rootfs切换到磁盘文件系统


    二、主要函数调用过程

        图1描述了挂载rootfs的函数调用关系(图中红色部分),便于后面的分析。

        从图中发现,在挂载rootfs前会先挂载sysfs,这样做的原因是确保sysfs能够完整的记录下设备驱动模型。

        sysfs_init()完成注册和挂载sysfs文件系统的功能;init_rootfs()负责注册rootfs,init_mount_tree()负责挂载rootfs,并将init_task的命名空间与之联系起来。


                                       图1


    三、linux文件系统初始化

        vfs_cache_init()首先建立并初始化目录hashdentry_hashtable和索引节点hashinode_hashtable;然后设置内核可以打开的最大文件数;最后调用mnt_init()完成sysfsrootfs文件系统的注册和挂载。

        linux使用哈希表存储目录和索引节点,以提高目录和索引节点的查找效率;dentry_hashtable是目录哈希表,inode_hashtable是索引节点哈希表。


    四、挂载sysfs文件系统

        sysfs用来记录和展示linux驱动模型,sysfs先于rootfs挂载是为全面展示linux驱动模型做好准备。

        mnt_init()调用sysfs_init()注册并挂载sysfs文件系统,然后调用kobject_create_and_add()创建"fs"目录。

     

    1. 2735 err = sysfs_init();
    2. 2736 if (err)
    3. 2737 printk(KERN_WARNING "%s: sysfs_init error: %d ",
    4. 2738 __func__, err);
    5. 2739 fs_kobj = kobject_create_and_add("fs", NULL);
    6. 2740 if (!fs_kobj)
    7. 2741 printk(KERN_WARNING "%s: kobj create error ", __func__);

        下面详细介绍sysfs文件系统的挂载过程:

        1sysfs_init()调用register_filesystem()注册文件系统类型sysfs_fs_type,并加入到全局单链表file_systems中。sysfs_fs_type定义如下,.mount成员函数负责超级块、根目录和索引节点的创建和初始化工作。

     

    1. 173 err = register_filesystem(&sysfs_fs_type);
    2. 174 if (!err) {
    3. 175 sysfs_mnt = kern_mount(&sysfs_fs_type);
    4. 176 if (IS_ERR(sysfs_mnt)) {
    5. 177 printk(KERN_ERR "sysfs: could not mount! ");
    6. 178 err = PTR_ERR(sysfs_mnt);
    7. 179 sysfs_mnt = NULL;
    8. 180 unregister_filesystem(&sysfs_fs_type);
    9. 181 goto out_err;
    10. 182 }
    1. 152 static struct file_system_type sysfs_fs_type = {
    2. 153 .name = "sysfs",
    3. 154 .mount = sysfs_mount,
    4. 155 .kill_sb = sysfs_kill_sb,
    5. 156 .fs_flags = FS_USERNS_MOUNT,
    6. 157 };

        2sysfs_init()->kern_mount()->vfs_kern_mount()创建并初始化struct mount挂载点,并使用全局变量sysfs_mnt保存该挂载点的挂载项(mnt成员)

     

    1. 783 mnt = alloc_vfsmnt(name);
    2. 784 if (!mnt)
    3. 785 return ERR_PTR(-ENOMEM);

        3kern_mount()调用sysfs_fs_type的.mount成员sysfs_mount()创建并初始化超级块、根目录'/'、根目录的索引节点等数据结构;并且把超级块添加到全局单链表super_blocks中,把索引节点添加到hashinode_hashtable和超级块的inode链表中。

        目前,我们可以得出一个重要结论:kern_mount()主要完成挂载点、超级块、根目录和索引节点的创建和初始化操作,可以看成是一个原子操作,这个函数以后会频繁使用。

     

    1. 790 root = mount_fs(type, flags, name, data);
    2. 1091 struct dentry *
    3. 1092 mount_fs(struct file_system_type *type, int flags, const char *name, void*data)
    4. 1093 {
    5. 1094 struct dentry *root;
    6. ...
    7. 1108
    8. 1109 root = type->mount(type, flags, name, data);
    1. 107 static struct dentry *sysfs_mount(struct file_system_type *fs_type,
    2. 108 int flags, const char *dev_name, void *data)
    3. 109 { ...
    4. 112 struct super_block *sb;
    5. ...
    6. 125 sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);
    7. ...
    8. 130 if (!sb->s_root) {
    9. 131 error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);

          4vfs_kern_mount()初始化挂载点的根目录和超级块。

     

    1. 796 mnt->mnt.mnt_root = root;
    2. 797 mnt->mnt.mnt_sb = root->d_sb;
    3. 798 mnt->mnt_mountpoint = mnt->mnt.mnt_root;
    4. 799 mnt->mnt_parent = mnt;

        5mnt_init()调用kobject_create_and_add()创建"fs"目录。

        通过以上步骤,sysfs文件系统在VFS中的视图如图2所示:挂载点指向超级块和根目录;超级块处在super_blocks单链表中,并且链接起所有属于该文件系统的索引节点;根目录'/'和目录"fs"指向各自的索引节点;为了提高查找效率,索引节点保存在hash表中。


                        图2


    五、挂载rootfs文件系统

        mnt_init()调用init_rootfs()注册rootfs,然后调用init_mount_tree()挂载rootfs

        下面详细介绍rootfs文件系统的挂载过程:
        1mnt_init()调用init_rootfs()注册文件系统类型rootfs_fs_type,并加入到全局单链表file_systems中。

    rootfs_fs_type定义如下,mount成员函数负责超级块、根目录和索引节点的建立和初始化工作。

    1. 265 static struct file_system_type rootfs_fs_type = {
    2. 266 .name = "rootfs",
    3. 267 .mount = rootfs_mount,
    4. 268 .kill_sb = kill_litter_super,
    5. 269 };
        2init_mount_tree()调用vfs_kern_mount()挂载rootfs文件系统,详细的挂载过程与sysfs文件系统类似,不再赘述。

        3init_mount_tree()调用create_mnt_ns()创建命名空间,并设置该命名空间的挂载点为rootfs的挂载点,同时将rootfs的挂载点链接到该命名空间的双向链表中。

    1. 2459 static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
    2. 2460 {
    3. 2461 struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
    4. 2462 if (!IS_ERR(new_ns)) {
    5. 2463 struct mount *mnt = real_mount(m);
    6. 2464 mnt->mnt_ns = new_ns;
    7. 2465 new_ns->root = mnt;
    8. 2466 list_add(&mnt->mnt_list, &new_ns->list);
    9. 2467 }

        4init_mount_tree()设置init_task的命名空间,同时调用set_fs_pwd()set_fs_root()设置init_task任务的当前目录和根目录为rootfs的根目录'/'

    1. 2696 ns = create_mnt_ns(mnt);
    2. 2697 if (IS_ERR(ns))
    3. 2698 panic("Can't allocate initial namespace");
    4. 2699
    5. 2700 init_task.nsproxy->mnt_ns = ns;
    6. 2701 get_mnt_ns(ns);
    7. 2702
    8. 2703 root.mnt = mnt;
    9. 2704 root.dentry = mnt->mnt_root;
    10. 2705
    11. 2706 set_fs_pwd(current->fs, &root);
    12. 2707 set_fs_root(current->fs, &root);

        通过以上分析,我们发现sysfsrootfs的区别在于:虽然系统同时挂载了sysfsrootfs文件系统,但是只有rootfs处于init_task进程的命名空间内,也就是说系统当前实际使用的是rootfs文件系统。

        此时,sysfsrootfsVFS中的视图如图3所示:为了突出主要关系,省略了挂载点指向超级块和根目录。
    从图中看出,rootfs处于进程的命名空间中,并且进程的fs_struct数据结构的rootpwd都指向了rootfs的根目录'/',所以用户实际使用的是rootfs文件系统。另外,rootfsVFS提供了'/'根目录,所以文件操作和文件系统的挂载操作都可以在VFS上进行了。


                       图3

    六、总结

        linux文件系统在初始化时,同时挂载了sysfsrootfs文件系统,但是只有rootfs处于进程的命名空间中,且进程的root目录和pwd目录都指向rootfs的根目录。至此,linuxVFS已经准备好了根目录(rootfs的根目录'/'),此时用户可以使用系统调用对VFS树进行扩展。


    版权声明:

        原创作品,如非商业性转载,请注明出处;如商业性转载出版,请与作者联系。

  • 相关阅读:
    单例模式
    HashSet、LinkedHashSet、SortedSet、TreeSet
    ArrayList、LinkedList、CopyOnWriteArrayList
    HashMap、Hashtable、LinkedHashMap
    andrew ng machine learning week8 非监督学习
    andrew ng machine learning week7 支持向量机
    andrew ng machine learning week6 机器学习算法理论
    andrew ng machine learning week5 神经网络
    andrew ng machine learning week4 神经网络
    vue组件监听属性变化watch方法报[Vue warn]: Method "watch" has type "object" in the component definition. Did you reference the function correctly?
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/13803433.html
Copyright © 2011-2022 走看看