转自: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. 网络助手的NABCD分析

    我们小组这次做的软件名字叫为校园网络助手.本校校园网分为内网与外网认证两种,并且有着流量限制,所以我们设计出来了这项软件,它主要有着两项功能:一键WIFI与校内网盘. N--need.在学校里每当流量 ...

  2. SQL Sever——远程过程调用失败(0x800706be)

    最近重装了系统,VS和SQL Sever莫名奇妙的不能用了.下面总结一下这个过程中遇到的问题,跟大家分享一下经验~~ 大概是以前的安装过程都十分顺利,这次,在尝试了数次登陆不上去之后,我仍然怀疑是自己 ...

  3. JS开发之CommonJs和AMD/CMD规范

    CommonJS是主要为了JS在后端的表现制定的,他是不适合前端的,AMD(异步模块定义)出现了,它就主要为前端JS的表现制定规范. 在兼容CommonJS的系统中,你可以使用JavaScript开发 ...

  4. 什么是GPS的冷启动、温启动和热启动?

    对于GPS多种启动方式的概念还很模糊,冷启动.热启动.温启动各种专业术语铺天盖地,使得许多用户眼花缭乱. 我们简单从定义上了解一下几种GPS启动的方式,GPS开机启动分为冷启动.温启动.热启动三种. ...

  5. Alpha发布评价

    1.奋斗吧兄弟组 食物链系统 是一个比较成熟的工具,可以应用于生物课程的辅助讲解,具有很强的软件目的性和实用性. 2.Newbee 俄罗斯方块 因为选了很经典的游戏,所以在创新上下了一定功夫,可是没有 ...

  6. (转)linux 内存管理——内核的shmall 和shmmax 参数

    内核的 shmall 和 shmmax 参数 SHMMAX= 配置了最大的内存segment的大小 ------>这个设置的比SGA_MAX_SIZE大比较好. SHMMIN= 最小的内存seg ...

  7. Hbase远程连接:Can't get the locations

    当Java API远程连接出错:Can't get the locations 原先填入的是IP地址,后来改为HOSTS文件中配置的主机名问题解决,如下红色字体部分: conf.set("h ...

  8. CF 1070J Streets and Avenues in Berhattan

    DP的数组f其实开得不够大,应该开200000,但是它在cf上就是过了... 题意是把一堆字母分别分配到行和列. 分析一下,答案实际上只和n行中和m列中每种字母分配的个数有关.而且答案只和" ...

  9. P2824 [HEOI2016/TJOI2016]排序

    题面 这是一道非常巧妙的线段树的题 我们会发现维护\(1 \sim n\)的序列非常困难,但如果我们维护\(01\)序列的的顺序,就非常容易了 但是我们怎么能把这道题变成维护\(01\)序列的顺序呢? ...

  10. hdu 5274 Dylans loves tree (树链剖分 + 线段树 异或)

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...