linux文件系统初始化过程(2)---挂载rootfs文件系统
一、目的
本文主要讲述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()首先建立并初始化目录hash表dentry_hashtable和索引节点hash表inode_hashtable;然后设置内核可以打开的最大文件数;最后调用mnt_init()完成sysfs和rootfs文件系统的注册和挂载。
linux使用哈希表存储目录和索引节点,以提高目录和索引节点的查找效率;dentry_hashtable是目录哈希表,inode_hashtable是索引节点哈希表。
四、挂载sysfs文件系统
sysfs用来记录和展示linux驱动模型,sysfs先于rootfs挂载是为全面展示linux驱动模型做好准备。
mnt_init()调用sysfs_init()注册并挂载sysfs文件系统,然后调用kobject_create_and_add()创建"fs"目录。
下面详细介绍sysfs文件系统的挂载过程:
1、sysfs_init()调用register_filesystem()注册文件系统类型sysfs_fs_type,并加入到全局单链表file_systems中。sysfs_fs_type定义如下,.mount成员函数负责超级块、根目录和索引节点的创建和初始化工作。
err = register_filesystem(&sysfs_fs_type);
if (!err) {
sysfs_mnt = kern_mount(&sysfs_fs_type);
if (IS_ERR(sysfs_mnt)) {
printk(KERN_ERR "sysfs: could not mount!\n");
err = PTR_ERR(sysfs_mnt);
sysfs_mnt = NULL;
unregister_filesystem(&sysfs_fs_type);
goto out_err;
}
2、sysfs_init()->kern_mount()->vfs_kern_mount()创建并初始化struct mount挂载点,并使用全局变量sysfs_mnt保存该挂载点的挂载项(mnt成员)。
3、kern_mount()调用sysfs_fs_type的.mount成员sysfs_mount()创建并初始化超级块、根目录'/'、根目录的索引节点等数据结构;并且把超级块添加到全局单链表super_blocks中,把索引节点添加到hash表inode_hashtable和超级块的inode链表中。
目前,我们可以得出一个重要结论:kern_mount()主要完成挂载点、超级块、根目录和索引节点的创建和初始化操作,可以看成是一个原子操作,这个函数以后会频繁使用。
mnt->mnt.mnt_root = root;
mnt->mnt.mnt_sb = root->d_sb;
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt; 、mnt_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文件系统的挂载过程:
1、mnt_init()调用init_rootfs()注册文件系统类型rootfs_fs_type,并加入到全局单链表file_systems中。
rootfs_fs_type定义如下,mount成员函数负责超级块、根目录和索引节点的建立和初始化工作。
2、init_mount_tree()调用vfs_kern_mount()挂载rootfs文件系统,详细的挂载过程与sysfs文件系统类似,不再赘述。
3、init_mount_tree()调用create_mnt_ns()创建命名空间,并设置该命名空间的挂载点为rootfs的挂载点,同时将rootfs的挂载点链接到该命名空间的双向链表中。
4、init_mount_tree()设置init_task的命名空间,同时调用set_fs_pwd()和set_fs_root()设置init_task任务的当前目录和根目录为rootfs的根目录'/'。
通过以上分析,我们发现sysfs和rootfs的区别在于:虽然系统同时挂载了sysfs和rootfs文件系统,但是只有rootfs处于init_task进程的命名空间内,也就是说系统当前实际使用的是rootfs文件系统。
此时,sysfs和rootfs在VFS中的视图如图3所示:为了突出主要关系,省略了挂载点指向超级块和根目录。
从图中看出,rootfs处于进程的命名空间中,并且进程的fs_struct数据结构的root和pwd都指向了rootfs的根目录'/',所以用户实际使用的是rootfs文件系统。另外,rootfs为VFS提供了'/'根目录,所以文件操作和文件系统的挂载操作都可以在VFS上进行了。
六、总结
linux文件系统在初始化时,同时挂载了sysfs和rootfs文件系统,但是只有rootfs处于进程的命名空间中,且进程的root目录和pwd目录都指向rootfs的根目录。至此,linux的VFS已经准备好了根目录(rootfs的根目录'/'),此时用户可以使用系统调用对VFS树进行扩展。
linux文件系统初始化过程(2)---挂载rootfs文件系统的更多相关文章
- linux文件系统初始化过程(6)---执行init程序
一.目的 内核加载完initrd文件后,为挂载磁盘文件系统做好了必要的准备工作,包括挂载了sysfs.proc文件系统,加载了磁盘驱动程序驱动程序等.接下来,内核跳转到用户空间的init程序,由ini ...
- linux文件系统初始化过程(5)---加载initrd(下)
一.目的 linux把文件分为常规文件.目录文件.软链接文件.硬链接文件.特殊文件(设备文件.管道文件.socket文件等)几种类型,分别对应不同的新建函数sys_open().sys_mkdir() ...
- linux文件系统初始化过程(1)---概述
术语表: struct task:进程 struct mnt_namespace:命名空间 struct mount:挂载点 struct vfsmount:挂载项 struct file:文件 st ...
- linux文件系统初始化过程(3)---加载initrd(上)
一.目的 本文主要讲述linux3.10文件系统初始化过程的第二阶段:加载initrd. initrd是一个临时文件系统,由bootload负责加载到内存中,里面包含了基本的可执行程序和驱动程序.在l ...
- 文件系统的挂载(2)---挂载rootfs文件系统
一.目的 本文主要讲述linux内核rootfs文件系统的挂载过程,内核版本为3.10. rootfs是基于内存的文件系统,没有实际的存储设备,所有操作都在内存中完成.为了保证linux内核的精简性, ...
- linux(centos)下挂载nefs文件系统
有时候,在将硬盘插到Linux系统上,挂载硬盘时一直提示:unknown filesystem type 'ntfs'.在尝试网上的方法也遇到了一些问题. 这是有的 linux 发行版并不默认支持挂载 ...
- linux文件系统初始化过程(4)---加载initrd(中)
一.目的 上文详细介绍了CPIO格式的initrd文件,本文从源代码角度分析加载并解析initrd文件的过程. initrd文件和linux内核一般存储在磁盘空间中,在系统启动阶段由bootload负 ...
- linux(centos)下挂载ntfs文件系统
在将硬盘插到Linux系统上,打开硬盘时一直提示:unknown filesystem type 'ntfs'.在尝试网上的方法也遇到了一些问题. 下面按照遇到的问题,按照正确的方式注意操作从而避免问 ...
- Linux系统初始化过程及运行级别简介
Linux开机过程: 1 开机自检(BIOS):初始化硬件,查找启动介质 2 MBR引导 3 GRUB引导菜单:GRUB程序安装在Bootloader 4 加载内核(kernel) 5 运行INIT进 ...
随机推荐
- 激活函数(relu,prelu,elu,+BN)对比on cifar10
激活函数(relu,prelu,elu,+BN)对比on cifar10 可参考上一篇: 激活函数 ReLU.LReLU.PReLU.CReLU.ELU.SELU 的定义和区别 一.理论基础 ...
- Android MVP Plugin,一键完成MVP结构代码编写
推荐一个Gradle的学习系列,Gradle相关的知识一直很匮乏,难得发现一个不错的系列: http://www.cnblogs.com/davenkin/p/gradle-learning-1.ht ...
- Windows win7下VMware Virtual Ethernet Adapter未识别网络解决方法
win7下VMware Virtual Ethernet Adapter未识别网络解决方法[摘] by:授客 QQ:1033553122 问题描述 win7系统下安装VMware,查看网卡适配器设置, ...
- ios虚拟机安装 (三)
安装mac系统出现欢迎使用的界面-->一直继续(个人设定) 点击左上角-->Dock-->启动放大 Safari 浏览器
- ubuntu 命令、linux环境变量设置
解压与压缩: tar.gz格式tar -xzvf xxx jar格式jar -xvf xxx.jar zip格式unzip xxx.zip zip -r xxx.zip xxx unarunar -e ...
- jenkins集成caliper"
1.jenkins安装caliper-ci插件(Caliper CI Plugin) 2.编写microbench 最简便的办法就是作为单元测试来跑(这样就不用在jenkins里配置跑microben ...
- [WinCE] Win CE 屏幕截图
VS2005自带了这个工具,这个工具的名称为:“远程放大”,其路径为:"C:\Program Files\CE Remote Tools\5.01\bin\cczoom.exe" ...
- 判断js对象类型
javascript中检测对象的类型的运算符有:typeof.constructor.instanceof.prototype. 1.typeof typeof是一个一元运算符,返回结果是一个说明运算 ...
- Redis学习---Redis的免密操作
Redis的免密操作 问题解决[方式一]:当前这种linux配置redis密码的方法是一种临时的,如果redis重启之后密码就会失效 1.首先进入redis,如果没有开启redis则需要先开启: [r ...
- IntelliJ IDEA2017/2018 激活方法 破解补丁激活(亲测可用)(注册码方法以和谐)
IntelliJ IDEA2017 激活方法(注册码方法以和谐): 搭建自己的授权服务器,对大佬来说也很简单,我作为菜鸟就不说了,网上有教程. 我主要说第二种,现在,直接写入注册码,是不能成功激活的( ...