热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Mountnamespacesandsharedsubtrees

挂载命名空间是创建每-用户和每-容器文件系统树的强大而灵活的工具。本文中,我们将仔细研究共享子树特性,它可通过自动、可控的方式在挂载命名空间之间传播挂载

挂载命名空间是创建每-用户和每-容器文件系统树的强大而灵活的工具。本文中,我们将仔细研究共享子树特性,它可通过自动、可控的方式在挂载命名空间之间传播挂载和卸载事件。

引言

挂载命名空间是第一个添加到 Linux 的命名空间类型,出现在 2002 年的 Linux 2.4.19 中。它们可隔离命名空间中的进程所看到的挂载点列表。换言之,每个挂载命名空间都有自己的挂载点列表,这意味着不同命名空间中的进程可以看到并操作单个目录层次结构的不同视图。

当系统首次启动时,有一个单一的挂载命名空间,即所谓的“初始命名空间”。带 CLONE_NEWNS 标志的 clone()(在新命名空间中创建新子进程)或 unshare()(将调用方移到新命名空间中)可创建新的挂载命名空间。当新的装挂载名空间被创建时,它将接收从 clone() 或 unshare() 的调用者的命名空间复制的挂载点列表。

在 clone() 或 unshare() 之后,可以在每个命名空间中独立地添加和删除挂载点(通过 mount() 和 umount() )。对挂载点列表的更改(默认情况下)仅对进程所在的挂载命名空间中的进程可见;这些更改在其他挂载命名空间中不可见。

挂载命名空间有多种用途。例如,可以提供文件系统的每个用户视图。还有其它用途,可以为新的 PID 命名空间挂载 /proc 文件系统,而不会对其它进程造成副作用,还可通过 chroot() 将进程隔离到单个目录层次结构中。在某些用例中,挂载命名空间与绑定挂载一起使用。

共享子树

挂载命名空间实现后,用户空间的程序员就遇到了一个可用性问题:挂载命名空间在命名空间之间提供了太多的隔离。例如,假设一个新磁盘加载到一个光盘驱动器中。在原来实现中,使该磁盘在所有挂载命名空间中可见的唯一方法是在每个命名空间中分别挂载该磁盘。但在许多情况下,最好仅执行一个挂载操作,就可使磁盘在系统上的所有挂载命名空间(或某些子集)中可见。

因此,共享子树特性被添加到 Linux 2.6.15 中(在 2006 年初,即大约挂载命名空间实现了三年后)。共享子树的主要优点是允许在命名空间之间自动、可控地传播装载和卸载事件。这意味着,例如,在一个挂载命名空间中挂载一个光盘可能会使得所有其他命名空间中都挂载该光盘。

在共享子树特性下,每个挂载点都用“传播类型”标记,该类型决定在此挂载点下创建和删除的挂载点是否传播到其他挂载点。有四种不同的传播类型:

  • MS_SHARED:此挂载点与同一“对等组”中的其它挂载点共享挂载和卸载事件(下面将更详细地描述)。当在此挂载点下添加或删除挂载点时,此更改将传播到对等组,因此挂载或卸载也会发生在每个对等挂载点。传播也会反向进行,因此对等挂载上的挂载和卸载事件也会传播到此挂载点。
  • MS_PRIVATE:与共享装载点相反。装载点不会将事件传播到任何对等方,也不会从任何对等方接收传播事件。
  • MS_SLAVE:这种传播类型介于共享挂载和私有挂载之间。从装载有一个主挂载—一个共享对等组,其成员将挂载和卸载事件传播到从装载。但是,从装载不会将事件传播到主挂载对等组。
  • MS_UNBINDABLE:该挂载点不可绑定。与私有装载点一样,此装载点不会将事件传播到对等方或接收来自对等方传播的事件。此外,此挂载点不能作为绑定挂载操作的源。

值得对上面几点进行扩展。首先,传播类型是一个每–挂载点–配置。在命名空间中的,某些挂载点可能标记为共享,而其他挂载点则标记为私有(或从属或不可绑定)。

要强调的第二点是,传播类型决定了在挂载点下挂载和卸载事件的传播。因此,如果在共享挂载 X 下创建了子挂载 Y,则该子挂载将传播到对等组中的其它挂载点。但是,X 的传播类型不会影响在 Y 下创建和删除的挂载点;Y 下的事件的传播与否取决于对 Y 传播类型的定义。类似地,当 X 被卸载时,卸载事件是否会传播取决于其父挂载点为其定义的传播类型。

顺便说一句,也许值得澄清的是,“事件”这个词在这里被用作一个抽象的术语,意思是“发生了什么事”。事件传播的概念并不意味着在挂载点之间传递某种类型的消息。相反,它的思想是,一个挂载点上的某个挂载或卸载操作触发了一个或多个其它挂载点上的相同操作。

最后,挂载既可以是主对等组的从属,也可以与它自己的对等组(即所谓的主从和共享挂载)共享事件。在这种情况下,挂载可能从主服务器接收传播事件,然后这些事件将传播到其对等服务器。

对等组

对等组是一组挂载点,它们互相传播挂载和卸载事件。当传播类型是共享的挂载点在创建新命名空间时被复制或作为绑定挂载的源时,对等组会获得新成员。(对于绑定挂载,其细节比我们这里描述的要复杂得多;具体可查看内核源文件 Documentation/filesystems/sharedsubtree.txt )。在这两种情况下,新挂载点都会成为现有挂载点的对等组的成员。相反,挂载点在卸载时不再是对等组的成员,无论是显式的还是隐式的,如当挂载命名空间的最后一个成员进程终止或移动到另一个命名空间。

例如,假设在运行于最初挂载命名空间中的 shell 中,我们将根挂载点设为私有,并创建两个共享挂载点:

sh1# mount --make-private /
sh1# mount --make-shared /dev/sda3 /X
sh1# mount --make-shared /dev/sda5 /Y

shell 中的“#” 表明,在 shell 会话中使用各种挂载命令来创建挂载点并更改其传播类型时,必须使用特权。

然后,在第二个终端上,我们使用 unshare 命令创建一个新的挂载命名空间,在其中运行 shell:

sh2# unshare -m --propagation unchanged sh

(-m 选项创建一个新的挂载命名空间;后面将解释 --propagation unchanged 的用途。)

返回到第一个终端,创建一个对 /X 挂载点的绑定挂载:

sh1# mkdir /Z
sh1# mount --bind /X /Z

按照这些步骤,我们将看到下图所示的情况。
在这里插入图片描述
在这种情况下,有两个对等组:

  • 第一个对等组包含挂载点 X、X’(挂载点 X 的副本)和 Z(对最初命名空间中源挂载点 X 的绑定挂载)。
  • 第二个对等组包含挂载点 Y 和 Y’(挂载点 Y 的副本)。

请注意,在创建第二个命名空间后才在最初命名空间中创建的绑定挂载 Z,并没有被复制到第二个命名空间,因为父挂载(/)被标记为私有。

通过 /proc/pid/mountinfo 检查传播类型和对等组

/proc/pid/mountinfo 文件(记录在 proc(5) 手册页中)显示了有关进程 PID 所在挂载命名空间中的挂载点的信息。位于同一挂载命名空间中的所有进程都将在此文件中看到相同的视图。此文件旨在提供比旧的、不可扩展的 /proc/pid/mounts 文件更多的挂载点信息。此文件中的每个记录中都包含一组(可能为空)“可选字段”,这些字段显示每个挂载的传播类型和对等组(用于共享挂载)信息。

对于共享装载,/proc/pid/mountinfo 中相应记录中的可选字段将包含 shared:N 形式的标记。这里,shared 标记表示挂载正与对等组共享传播事件。对等组由 N 标识,N 是唯一标识对等组的整数值。这些 ID 从 1 开始编号,当一个对等组不存在后还可循环使用。同一对等组的所有挂载点在 /proc/pid/mountinfo 文件中的 shared:N 标记相同。

因此,例如,如果我们在上面示例中的第一个 shell 中列出 /proc/self/mountinfo 的内容,将看到以下内容(使用 sed 过滤掉一些不相关的信息):

sh1# cat /proc/self/mountinfo | sed 's/ - .*//'
61 0 8:2 / / rw,relatime
81 61 8:3 / /X rw,relatime shared:1
124 61 8:5 / /Y rw,relatime shared:2
228 61 8:3 / /Z rw,relatime shared:1

从该输出中,我们首先看到根挂载点是私有的,因为可选字段中没有任何标记。我们还看到,挂载点 /X 和 /Z 位于同一对等组(ID 为1),这意味着这两个挂载下的挂载和卸载事件将互相传播。 /Y 是另一个对等组(ID 2)中的共享装载,根据定义,它不会与对等组 1 中的挂载点相互传播事件。

还可通过 proc/pid/mountinfo 文件查看挂载点之间的父子关系。每个记录中的第一个字段是挂载点的 ID。第二个字段是父挂载的 ID。从上面的输出中,我们可以看到挂载点 /X、/Y 和 /Z 都是根挂载的子项,因为它们的父 ID 都是 61。

在第二个 shell(在第二个命名空间)中运行相同的命令,我们看到:

sh2# cat /proc/self/mountinfo | sed 's/ - .*//'
147 146 8:2 / / rw,relatime
221 147 8:3 / /X rw,relatime shared:1
224 147 8:5 / /Y rw,relatime shared:2

再次,我们看到根挂载点是私有的。然后我们看到 /X 是对等组 1 中的共享挂载,与最初挂载命名空间中的挂载 /X 和 /Z 相同。最后,我们看到 /Y 是对等组 2 中的共享装载,与最初挂载名空间中的挂载 /Y 相同。最后要注意的是,在第二个命名空间中复制的挂载点有自己的 ID,与最初命名空间中相应挂载的 ID 不同。

默认值讨论

由于情况有点复杂,到目前为止,我们避免讨论新挂载点的默认传播类型。从内核的角度来看,新挂载的默认值如下:

  • 如果挂载点有父亲(即非根挂载点),并且父亲的传播类型是 MS_SHARED,则新挂载点的传播类型也是 MS_SHARED。
  • 否则,新挂载的传播类型为 MS_PRIVATE。

根据这些规则,如果根挂载是 MS_PRIVATE,默认情况下,所有子挂载也将是 MS_PRIVATE。不过,MS_SHARED 是一个更好的默认值,是更常用的传播类型。因此,systemd 将所有挂载点的传播类型设置为 MS_SHARED。所以,在大多数现代 Linux 发行版上,默认的传播类型是 MS_SHARED。不过,util-linux 的 unshare 特性却不这样认为。在创建新的挂载命名空间时,unshare 假定用户需要完全隔离的命名空间,并通过执行以下命令(该命令递归地将根目录下的所有挂载标记为私有)将所有挂载点设置为私有:

mount --make-rprivate /

为了防止出现这种情况,我们可以在创建新命名空间时使用其它选项:

unshare -m --propagation unchanged <cmd>

结束语

在本文中&#xff0c;我们介绍了挂载命名空间和共享子树的“理论”。我们现在有足够的信息来证明和理解各种传播类型的语义&#xff1b;这将是后续文章的主题。


原文&#xff1a;https://lwn.net/Articles/689856/
公众号&#xff1a;Geek乐园
云&#43;社区&#xff1a;https://cloud.tencent.com/developer/column/4124


推荐阅读
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Python15行代码实现免费发送手机短信,推送消息「建议收藏」
    Python15行代码实现免费发 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 【Windows】实现微信双开或多开的方法及步骤详解
    本文介绍了在Windows系统下实现微信双开或多开的方法,通过安装微信电脑版、复制微信程序启动路径、修改文本文件为bat文件等步骤,实现同时登录两个或多个微信的效果。相比于使用虚拟机的方法,本方法更简单易行,适用于任何电脑,并且不会消耗过多系统资源。详细步骤和原理解释请参考本文内容。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 本文介绍了Composer依赖管理的重要性及使用方法。对于现代语言而言,包管理器是标配,而Composer作为PHP的包管理器,解决了PEAR的问题,并且使用简单,方便提交自己的包。文章还提到了使用Composer能够避免各种include的问题,避免命名空间冲突,并且能够方便地安装升级扩展包。 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • 本文介绍了Python语言程序设计中文件和数据格式化的操作,包括使用np.savetext保存文本文件,对文本文件和二进制文件进行统一的操作步骤,以及使用Numpy模块进行数据可视化编程的指南。同时还提供了一些关于Python的测试题。 ... [详细]
  • 在IDEA中运行CAS服务器的配置方法
    本文介绍了在IDEA中运行CAS服务器的配置方法,包括下载CAS模板Overlay Template、解压并添加项目、配置tomcat、运行CAS服务器等步骤。通过本文的指导,读者可以轻松在IDEA中进行CAS服务器的运行和配置。 ... [详细]
author-avatar
红殿_真红王道哥哥
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有