转自:https://blog.csdn.net/zr_lang/article/details/40343899

引言

写到这里我们已经从mount文件系统调用的入口开始,分析到内核的mount,通过VFS层进入到具体文件系统实现的mount函数,最终得到具体文件系统的super block信息后构建出一个新的struct mount结构,返回给do_add_mount继续下面的操作。本来在这节我想从do_add_mount的代码开始把mount最后一部分——加入全局文件系统树讲完。但是写到一半我发现自己写不下去了,因为单纯的对代码进行注释没有办法解释很多基本的问题,到底挂载实例和文件系统有什么关系?我觉得不把这个说一下没有办法往下写,所以插入这样一节,我们来看一下挂载实例(struct mount/ struct vfsmount)和super block, dentry, inode, file_system_type的关系,以及一个文件系统挂载到另一个文件系统下时到底是怎么样的关系。

为了说明的方便,我们下面以这样的场景为例进行描述:

1. 系统中有xfs, ext2和minix等若干文件系统模块

2. 现有/dev/sda1和/dev/sdb1上存在xfs文件系统,/dev/sda2上为ext2文件系统,/dev/sdc1上为minix文件系统

3. 将/dev/sda1挂载到/mnt/a上,将/dev/sdb1挂载到/mnt/b上,将/dev/sdc1不挂载

4. 在第三步之后,将/dev/sda2也挂载到/mnt/a上。再将/dev/sda1同时挂载到/mnt/x上

file_system_type + super block + mount的关系

从file_system_type到super_block到mount实例的角度来看,上述关系大致是这样的:

系统中存在三个文件系统,也就有三种file_system_type被注册。sda1和sdb1都是xfs文件系统,所以xfs的file_system_type的fs_supers把这两个同为xfs文件系统的super_block串连在自己下面。sda2是ext2文件系统,所以它挂在ext2的file_system_type下。sdc1是minix文件系统,在sdc1的设备上存在着super_block信息,但是我们这里说的super_block是指内存中的,由于sdc1没有被挂载使用,所以没有它的super_block信息被读入内存。

从挂载实例上看,sda1和sda2都挂载到/mnt/a上,但是从上述关系中很难表述它们的区别,需要借助mount和dentry的关系来说明,下面再具体说明。sda1同时挂在了/mnt/a和/mnt/x上,所以它有两个挂载实例对应同一个super_block。sdc1没有被挂载,所以没有挂载实例和它对应。

mount_hashtable是一个全局挂载实例的哈希表,系统中除了根挂载点以外所有的挂载实例都记录在它下面,搜索一个mount实例时需要借助这个mount的父mount实例和dentry实例来计算的出。比如说/mnt上挂载着一个文件系统,/mnt/a和b上分别又挂载着文件系统,此时要想检索/mnt/a(或b),需要以/mnt上的挂载实例和/mnt/a(或者b)的dentry结构为依据计算hash数值从mount_hashtable上得到一个头指针,这个头指针下就是所有父文件系统是在/mnt上且挂载点是/mnt/a(或b)的挂载到/mnt/a或b下的mount实例。(这里其实有一个不太容易注意到的地方,到底什么情况下同一个父文件系统下的同一个dentry下会有多个挂载实例呢?我们不在本文讨论,以后有机会再讨论这个问题。)

上图可以看出file_system_type, super_block和mount实例之间的关系,但是不能看出来父子文件系统之间的相互关系。下面让我们看一下当一个文件系统挂载到另一个文件系统的子目录下的情况。

父子挂载点的挂载关系

假设在/mnt上挂载着一个文件系统,根据上面条件我们以/dev/sda1挂载到/mnt/a上为例,来解释一下/mnt/b上这个挂载实例和/mnt的挂载实例的关系,如下图所示:

父文件系统代表/mnt上的文件系统,子文件系统代表/mnt/b上的文件系统(带颜色的地方为重点要注意的地方)。父子文件系统通过mnt_parent, mount_child, mnt_mounts等成员来联系在一起,每个挂载实例的mnt_sb都指向这个挂载实例所属文件系统的super_block。每个挂载实例的mnt_root都指向这个文件系统的根dentry。

根dentry就是一个文件系统的路径的起始,也就是"/"。比如一个路径名/mnt/a/dir/file。在/mnt/b这个文件系统下看这个文件是/dir/file,这个起始的"/"代表/mnt/a下挂载的文件系统的根,也就是如上图红色所示的dentry,它是这一文件系统的起始dentry。当发现到了一个文件系统的根后,如果想继续探寻完整路径应该根据/mnt/b的挂载实例向上找到其父文件系统,也就是/mnt下挂载的文件系统。/dev/sda1挂载在了/mnt/a上,这里的/mnt/a代表/mnt下文件系统的一个子dentry,如图绿色部分所示。注意红色和绿色是两个文件系统下的两个不同的dentry,虽然不是很恰当的说它们从全局来看是一个路径名。那么从/mnt所在的文件系统看/mnt/a就是/a。最后再往上就到了rootfs文件系统,也就是最上层的根"/"。所以我们之前说过,表示一个文件的路径需要<mount, dentry>二元组来共同确定。

子文件系统的mnt_mountpoint就指向了父文件系统的一个dentry,这个dentry也就是子文件系统的真正挂载点。可以说子文件系统在挂载后会新创建一个dentry,并在此构建这个文件系统下的路径结构。

宗上所述,/mnt/b上这个新挂载的文件系统创建了一个新的mount, super_block, 根inode和根dentry。在看懂了一个简单的父子文件系统挂载关系后,我们来看下多个文件系统挂载到同一路径名下时又是什么样子。

多文件系统单挂载点的挂载关系

就像上面所叙述的/dev/sda1挂载到了/mnt/a上,之后/dev/sda2也挂载到/mnt/a上的情况,当两个以上的文件系统先后挂载到同一个路径名下时会是怎样一种情况呢?如下图所示:

如上图,子文件系统A代表/dev/sda1,子文件系统B代表/dev/sda2。父文件系统和子文件系统A的挂载在之前一节已经说明过了,当/dev/sda2在sda1之后也挂载到/mnt/a上时,其关系就像在上一节基础上又添加了子文件系统B的关系。实际上子文件系统A就是子文件系统B的父文件系统,而唯一不同的是子文件系统B的mnt_mountpoint指向了子文件系统A的根dentry。而新的子文件系统B还是有自己的mount, super_block, 根dentry和根inode。

两个文件系统挂载在同一路径名下会造成之前挂载的文件系统被隐藏,这种实现我们在后续讲解。其实从上面的关系也应该可以想到一些解决的方式。最后再来看一下一个文件系统被挂载到多个不同的路径下的情况。

单文件系统多挂载点的挂载关系

同一个文件系统被挂载到不同的路经下,就像上面例子中/dev/sda1被挂载到/mnt/a和/mnt/x两个位置一样,如下图所示:

一个文件系统对应一个super_block,所以同一个文件系统当然只有一个super_block。但是因为挂载了两次,所有每一次挂载对应一个挂载实例struct mount,也就是有两个mount实例。此外同一个文件系统只有一个根,也就是两个挂载实例公用一个根dentry。但是因为挂载在两个不同的路经下,所以每个挂载实例的mnt_mountpoint指向不同的dentry。由于/mnt/a和/mnt/x都属于同一文件系统的下的两个子目录,所以两个子mount才指向同一个父mount(这个不是必须的)。

如果我们像讨论的再变态一点,在上述/mnt/a和/mnt/x的基础上在将两个不同的文件系统分别挂载到/mnt/a/dir和/mnt/x/dir上,想象一下这将是怎样一种情况和关系。这个我就不画出来了,有兴趣的可以思考一下。

本文讲到这里就先结束了,由于是个后文做一下必要知识的铺垫,在mount章节最后分析将mount加入全局文件系统树,以及后面的路径名解析中都有一些铺垫的作用。所以只是简单的罗列了一下不同情况下挂载关系的情况。上述的分析也只是代表我自己分析的观点,可能有些地方并不十分准确,还望各路大神纠正。

http://blog.csdn.net/zr_lang/article/details/40325241 (mount 七)

http://blog.csdn.net/zr_lang/article/details/40343899 (mount 六)

http://blog.csdn.net/zr_lang/article/details/40115013 (mount 五)

http://blog.csdn.net/zr_lang/article/details/40080979 (mount 四)

http://blog.csdn.net/zr_lang/article/details/40049305 (mount 三)

http://blog.csdn.net/zr_lang/article/details/40002285 (mount 二)

http://blog.csdn.net/zr_lang/article/details/39963253 (mount 一)

mount过程分析之六——挂载关系(图解)【转】的更多相关文章

  1. CGI、FastCGI和PHP-FPM关系图解

    CGI.FastCGI和PHP-FPM关系图解   webapp即是php解析器等 当Web Server收到 index.php 这个请求后,会启动对应的 CGI 程序,这里就是PHP的解析器.接下 ...

  2. Linux常见设备及相应/dev/xxx文件名、Mount Point、挂载点、Mount命令、fstab、挂载分区

    Linux 中的设备有2种类型:字符设备(无缓冲且只能顺序存取).块设备(有缓冲且可以随机存取).这些设备中,有些设备是对实际存在的物理硬件的抽象,而有些设备则是内核自身提供的功能(不依赖于特定的物理 ...

  3. 简单实用UML关系图解

    一句话UML,再记不住就要DPP了: 关系 图解 代码 备注 1:继承关系(Generalization)     2:实现关系(Realization)     3:依赖关系(Dependency) ...

  4. app.$mount("#app") 手动挂载

    $mount()手动挂载 当Vue实例没有el属性时,则该实例尚没有挂载到某个dom中: 假如需要延迟挂载,可以在之后手动调用vm.$mount()方法来挂载.例如: new Vue({ //el: ...

  5. centos samba/squid 配置 samba配置 smbclient mount fstab自动挂载samba curl -xlocalhost:3128 www.qq.com squid配置 3128 DNSPOD 第二十七节课

    centos  samba/squid 配置  samba配置 smbclient  mount fstab自动挂载samba curl -xlocalhost:3128 www.qq.com squ ...

  6. [转帖]UML类图关系图解

    UML类图关系图解 https://www.cnblogs.com/TvvT-kevin/p/9357339.html 一.类结构 在类的UML图中,使用长方形描述一个类的主要构成,长方形垂直地分为三 ...

  7. mount过程分析之一(基于3.16.3内核)【转】

    转自:https://blog.csdn.net/zr_lang/article/details/39963253 一直想写有些关于文件系统的博文,但是由于近一年来实在太忙,所以没有时间写.前几日赶上 ...

  8. mount/umount文件挂载

    用法: mount [-lhV] mount -a [选项] mount [选项] [--source] <源> | [--target] <目录> mount [选项] &l ...

  9. virtualBox+centos使用mount -t vboxsf挂载

    1.先确保virtualBox安装目录下有对应的文件VBoxGuestAdditions.iso 2.点击设备下的“安装增强功能”,之后再centos可视化界面一步一步点击即可 3.virtualBo ...

随机推荐

  1. 11慕课网《进击Node.js基础(一)》Buffer和Stream

    Buffer 用来保存原始数据 (logo.png) 以下代码读取logo.png为buffer类型 然后将buffer转化为string,新建png 可以将字符串配置: data:image/png ...

  2. 《Gogoing》Alpha版使用说明

    前言: Gogoing是由我们山药蛋团队利用课余时间,基于安卓安卓系统开发完成.该软件针对于我们大学生没有赚钱能力,却又渴望外面的世界,该软件的核心理念的是“穷”游.为当代的大学生提供一个景点推荐或者 ...

  3. Sprint计划会议内容

    项目名称:蹭课神器 会议内容 首先我们讨论了项目的工作量及实施流程 一.工作认领 二.界面的总体规划 三.主要功能的设计 四.设计数据库 五.编写项目报告 六.软件测试和推广 然后我们进行了工作认领, ...

  4. C++学习记录(留坑)

    #include <iostream> #include <ctime> #include <fstream> ///文件打开有o.i权限 #include < ...

  5. NAVICAT 12.0.24 连接 MYSQL8.0.12 的方法

    1. 自己本机安装破解的 navicat11 结果连接不上, 所以 升级了下 navicat 12.0.24 破解方法在: https://www.jianshu.com/p/42a33b0dda9c ...

  6. [转帖] tmux 的使用说明

    之前曾经看过 tmux 的简介 但是一直不会用 这次 看了下 原来是这么处理 不过 用windows 多了 还是感觉鼠标 操作多一些 全键盘操作的习惯 还是没有养成. 原贴地址: https://ww ...

  7. FuelPHP 系列(二) ------ route 路由

    FuelPHP 中,默认可以通过 /controller_name/function_name 这种方式来访问,也可以通过自定义路由来访问. 路由配置在 /fuel/app/config/routes ...

  8. Fantastic Graph 2018 沈阳赛区网络预赛 F题

    题意: 二分图 有k条边,我们去选择其中的几条 每选中一条那么此条边的u 和 v的度数就+1,最后使得所有点的度数都在[l, r]这个区间内 , 这就相当于 边流入1,流出1,最后使流量平衡 解析: ...

  9. pom.xml文件中,添加自定义参数Properties

    <properties> <powermock.version>1.6.6</powermock.version> </properties> < ...

  10. 【BZOJ1452】[JSOI2009]Count(树状数组)

    [BZOJ1452][JSOI2009]Count(树状数组) 题面 BZOJ 洛谷 题解 数据范围这么小?不是对于每个颜色开一个什么东西记一下就好了吗. 然而我不会二维树状数组? 不存在的,凭借多年 ...