浅谈Linux中的根文件系统

自作多情 提交于 2020-02-26 02:26:30

摘要
Linux中有一个让初学者都不是特别清楚的概念,叫做“根文件系统”。我接触Linux前前后后也好几年了,但是对这个问题,至今也不是特别清楚,至少没法给出一个很全面很到位的解释。于是,我们今天来理一理这个话题。
一、先交代一下文件系统
在开始讨论根文件系统这个话题之前,我们必首先交代一下文件系统这个概念。毕竟,根文件系统只是文件系统中的一种比较特殊的形式而已。根据百度百科:
文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。文件系统由三部分组成:文件系统接口,对对象操作和管理的软件集合,对象及属性。从系统角度来看,文件系统是对文件存储设备的空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。具体来说,他负责为用户建立文件,存入、读取、修改、转储文件、控制文件的存取,当用户不再使用时撤销文件等。
文件系统的重要性,我想大家都很清楚,不用多说了。这里有一句话,我觉得非常精辟而且到位的点出了文件系统在Linux中的重要性:
尽管内核是Linux的核心,但文件却是用户与操作系统交互所采取的主要工具。这对Linux来说由其如此,这是因为在UNINX传统中,他使用文件I/O机制管理硬件设备和数据文件。
二、什么是根文件系统
然后来解释一下“根文件系统”这个名词的基本概念。同样引自百度百科的解释:
根文件系统首先是内核启动时所mount的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。
展开来细说就是,根文件系统首先是一种文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但是相对于普通的文件系统,它的特殊之处在于,它是内核启动时所挂载(mount)的第一个文件系统,内核代码的映像文件保存在根文件系统中,系统引导启动程序会在根文件系统挂载之后从中把一些初始化脚本(如rcS,inittab)和服务加载到内存中去运行。我们要明白文件系统和内核是完全独立的两个部分。在嵌入式中移植的内核下载到开发板,是没有办法真正的启动Linux操作系统的,会出现无法加载文件系统的错误。
三、根文件系统为什么这么重要
根文件系统之所以在前面加一个根,说明他是加载其他文件系统的根,那么如果没有这个根,其他的文件系统就没办法进行加载的。
根文件系统包含系统启动时所必须的目录和关键性的文件,以及使其他文件系统得以挂载(mount)所必要的文件。例如:
init 进程的应用程序必须运行在根文件系统上;
根文件系统提供了根目录“/”;
linux挂载分区时所依赖的信息存放于根文件系统/etc/fstab这个文件中;
shell命令程序必须运行在根文件系统上,譬如ls,cd等命令;
总之:一套Linux体系,只有内核本身是不能工作的,必须要rootfs(/上的etc目录下的配置文件、/bin /sbin等目录下的shell命令,还有/lib目录下的库文件等...)相配合才能工作。
Linux启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。成功之后可以自动或手动挂载其他的文件系统。因此,一个系统中可以同时存在不同的文件系统。在Linux中将一个文件系统与一个存储设备关联起来的过程称为挂载(mount)。使用mount命令将一个文件系统附着到当前文件系统层次结构中(根)。在执行挂载时要提供文件系统类型、文件系统和一个挂载点。根文件系统被挂载到根目录下“/”上后,在根目录下就有根文件系统的各个目录,文件:/bin /sbin /mnt等,再将其他分区挂载到/mnt目录上,/mnt目录下就有这个分区的各个目录和文件。
四、如何在内核中挂载根文件系统
init/main.c->

 start_kernel()->vfs_caches_init(totalram_pages)–>

   mnt_init()–>

     / sysfs用来记录和展示linux驱动模型,sysfs先于rootfs挂载是为全面展示linux驱动模型做好准备 /
     / mnt_init()调用sysfs_init()注册并挂载sysfs文件系统,然后调用kobject_create_and_add()创建fs目录 /
     sysfs_init();

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

     init_mount_tree();
1、sysfs文件系统目前还没有挂载到rootfs的某个挂载点上,后续init程序会把sysfs挂载到rootfs的sys挂载点上;

2、rootfs是基于内存的文件系统,所有操作都在内存中完成;也没有实际的存储设备,所以不需要设备驱动程序的参与。基于以上原因,linux在启动阶段使用rootfs文件系统,当磁盘驱动程序和磁盘文件系统成功加载后,linux系统会将系统根目录从rootfs切换到磁盘文件系统。
start_kernel
  vfs_caches_init
    mnt_init
      init_rootfs注册rootfs文件系统
      init_mount_tree 挂载rootfs文件系统
        vfs_kern_mount
          mount_fs
            type->mount其实是rootfs_mount
              mount_nodev
                fill_super 其实是ramfs_fill_super
                  inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);
                  sb->s_root = d_make_root(inode);
                    static const struct qstr name = QSTR_INIT(“/”, 1);[1]
                    __d_alloc(root_inode->i_sb, &name);
          …
          mnt->mnt.mnt_root = root;[2
]
          mnt->mnt.mnt_sb = root->d_sb;[3]
          mnt->mnt_mountpoint = mnt->mnt.mnt_root;[4
]
          mnt->mnt_parent = mnt;[5*]
root.mnt = mnt;
        root.dentry = mnt->mnt_root;
        mnt->mnt_flags |= MNT_LOCKED;
        set_fs_pwd(current->fs, &root);
        set_fs_root(current->fs, &root);
  …
  rest_init
  kernel_thread(kernel_init, NULL, CLONE_FS);
在执行kernel_init之前,会建立roofs文件系统。

[1]处设置了根目录的名字为“/”;
[2
]处设置了vfsmount中的root目录;
[3]处设置了vfsmount中的超级块;
[4
]处设置了vfsmount中的文件挂载点,指向了自己;
[5*]处设置了vfsmount中的父文件系统的vfsmount为自己;
五、根文件系统各个常用目录介绍
正常来说,根文件系统至少包括以下目录:
/etc:存储重要的配置文件
/bin 存储常用且开机时必须用到的执行文件
/sbin:存储着开机过程中所需的系统执行文件
/lib:存储/bin及/sbin的执行文件所需的链接库,以及Linux的内核模块。
/dev:存储设备文件。
注:五大目录必须存储在根文件系统上,缺一不可。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!