黄东升: mount namespace和共享子树

2023-10-18 00:50

本文主要是介绍黄东升: mount namespace和共享子树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

没有一个mount namespace是一座孤岛

2


本文翻译自lwn上一个namespace系列文章的一篇,原文链接会在文末给出,各位看官开始进入mount namespace的世界吧!

Mount namespaces用来创建一个用户或者容器独立的文件系统树,是一个强大且灵活的工具。同时,mount namespaces也有一些比较复杂的特点。本文,作为一系列的namespace文章延续,将对这些复杂性进行解释。我们将更细致的说明一下共享子树(shared subtrees) 这个特征,通过共享子树,挂载(mount)和卸载(unmount)事件可以通过一种自动,可控的方式在不同的命名空间之间传递。

导论

Mount namespaces 是第一个进入Linux内核的namespace,首次出现在Linux 2.4.19版本。它们隔离了每个进程可以看到的挂载点列表,或者换句话说,每个Mount namespace都有它们自己的挂载点列表,意味着在不同namespace中的进程都可以看到且控制不同的目录层次结构(目录树)。

当系统启动时,只有一个“ 初始命名空间”。新的mount命名空间通过设置clone()系统调用中的CLONE_NEWNS来创建,或者通过unshare()系统调用将调用者迁移到一个新的命名空间。当一个新的命名空间被创建时,它将继承调用clone()和unshare()的进程的命名空间的全部挂载点列表(mount point list)

调用clone()或者unshare()之后,通过mount()或者unmount()函数,每个namespace中的挂载点可以被动态的删除或者增加。默认情况下,对挂载点列表的修改只对处于该命名空间的进程是可见的,对于其他命名空间中的进程则是无效的。

Mount namespaces 有多种用途。比如说,它们(指代命名空间)可以给每个用户提供一个独立的文件系统视图。其他的用途包括为新创建的pid namespaces挂载一个/proc文件系统,或者实现类似chroot() 的目录层次结构的隔离。在一些应用中,mount namespaces是和 bind mounts联合使用的。

共享子树(Shared subtrees)

在使用mount namespaces的过程中,用户空间的程序员可能会遇到一个难题:mount namespaces提供了过度的隔离。设想一下,当我们将一个光盘插入到光驱中,在初始的mount namespace中,令光盘在所有的namespace中可见的唯一方法是,将光盘挂载到每一个namespace中。在许多情况下,如果能够通过一次挂载就使得光盘对所有的namespace都是可见的,那么这将是一件十分绝佳的事情。

由于以上所描述的难题,共享子树机制被引进了Linux 2.6.15(2006年早期,大约是Mount namespace第一次发布后的三年)。共享子树最核心的特征是允许挂载和卸载事件以一种自动的,可控的方式在不同的namespaces间传递(propagation)。这就意味着,在一个命名空间中挂载光盘的同时也会触发对于其他namespace对同一张光盘的挂载。

在共享子树中,每个挂载点都都存在一个名为传递类型(propagation type)的标记,该标记决定了一个namespace中创建或者删除的挂载点是否会传递到其他的namespaces。

有四种传递类型:

  • MS_SHARED:该挂载点和它的 “对等组”(peer group,接下来会详细解释它)共享挂载和卸载事件。当一个挂载点被删除或者添加到namespace中,这些事件会被传递到它的对等组,这样挂载和卸载事件会发生在所有对等挂载点。传递也会发生在相反的方向。也就是说,事件的传递是双向的。

  • MS_PRIVATE:  和共享挂载相反,标记为private的事件不会传递到任何的对等组,挂载操作默认使用该标志。

  • MS_SLAVE:  这个传递类型介于shared 和 slave之间,一个slave mount拥有一个master(一个共享的对等组),该对等组中的成员可以将事件传递到他的slave mount。但是slave mount不能将事件传递给master mount。

  • MS_UNBINDABLE:  该挂载点是不可绑定的。

有几点值得展开说一下。第一点是传递类型是一个针对挂载点的设置(per-mount-point setting)。在一个命名空间中,一些挂载点被标记为 shared,其他的挂载点可以被标记为Private(或者slave, unbindable)。

第二点要说明的是,传递类型决定了挂载和卸载的传递。因此,在一个共享挂载X中创建一个子挂载 Y(表示挂载点Y是挂载点X的子目录),子挂载会传递到对等组的其他挂载中。然而,X的传递类型不会影响到在Y中创建或者删除的挂载点。Y中的事件是否会传递到其他的对等组中取决于Y的挂载类型。类似的,当X本身被卸载,该卸载事件是否会被传递,也同样取决于X的传递类型。

另外,有一点值得阐明的是,本文中的“事件(event)”是一个相对抽象的名词,意思是“有一些事情发生”。事件传递的概念并不意味着不同的挂载点之间的消息传递。恰恰相反,事件传递应该被阐述为当一个挂载点的挂载或者卸载事件发生时会触发其他挂载点的相同的事件。


Peer groups(对等组)

对等组是一组挂载点,并且一个对等组可以将挂载和卸载事件传递给另一个对等组。

举例来说,假设一个运行在初始mount namespace的shell,我们使得根挂载为private,并且创建两个共享的挂载点:

640?wx_fmt=png


建挂载点和改变传递类型需要root权限。

然后,在第二个窗口中,我们使用ushare()系统调用创建一个新的mount namespace,并在新的namespace中运行一个shell:

640?wx_fmt=png


-m 表示创建一个新的namespace,–propagation unchanged的意义我们随后解释)

返回到第一个窗口,我们使用绑定挂载将/X挂载到/Z。

完成这些步骤之后,命名空间和对等组的情况如下所示:

640?wx_fmt=png

这个场景中,有两个对等组:

  • 在第一个对等组中包含挂载点 X, X’( X的挂载点的拷贝在第二个命名空间被创建时),Z(由挂载点X绑定挂载得到)。

  • 第二个对等组包含挂载点Y和Y’(挂载点Y的复制品,当第二个命名空间被创建时)。

注意绑定挂载的挂载点Z,该挂载点在第一个命名空间中,当第二个命名空间被创建时创建,挂载点Z不会在第二个挂载点内被复制,因为父挂载点被标记为private。

译者记:可以看到即便是不同的namespace中的挂载点也是可能处于同一个对等组的。同时,只要一个挂载点是shared类型的,它就会传递到所有namespace中的对等组。 另外Peer group的翻译不是很恰当,希望读者能够提出自己的意见。


通过/proc/PID/mountinfo查看传递类型和对等组

/proc/PID/mountinfo显示的是进程PID所在的mount namespace 的挂载点信息。所有位于同一命名空间的进程都将看到相同的视图。该文件比/proc/PID/mounts能够提供更加丰富的信息。文件中的每一条记录都存在一个可选字段,该字段显示了挂载点的传递类型和对等组(共享挂载)该字段可以为空。

对于共享挂载,/proc/PID/mountinfo中的每条记录的可选字段都包含一个格式为 shared: N类型的标记。Shared标记表示该挂载点和同一对等组共享传递事件。对等组由整数N来标识。这些ID从1开始分配,如果一个对等组内的成员数为0,闲置的ID可能会被回收。

举例来说,如果我们在第一个shell中打印/proc/self/mountinfo,我们可以看到如下的输出:

640?wx_fmt=png


输出可以看到,在可选字段的shared标志为空,表明根挂载点是private。我们也可以看到挂载点/X和/Z属于同一个对等组(组ID = 1), 意味着挂载和卸载事件会在这两个挂载点之间传递。挂载点/Y属于另一个对等组(组ID = 2)。

/proc/PID/mountinfo文件让我们可以得到不同挂载点的亲属关系。每条记录的第一个字段是一个挂载点特有的ID。第二个字段是父挂载点的ID。从上述输出我们可以看到,挂载点/X /Y /Z的父挂载点ID是61。

在第二个窗口中(第二个namespace)打印/proc/PID/mountinfo, 我们可以看到:

640?wx_fmt=png


样的根目录是私有挂载点。/X属于第一个对等组,初始命名空间的/X和/Z同样属于第一个对等组。挂载点/Y则属于另一个对等组。最后一点需要说明的是,第二个namespace中的被复制过来的挂载点和它的另一个实体拥有不同的ID。

译者注,看了这么多,那么究竟一个对等组都包含那种类型的挂载点呢?可以看到,只要一个挂载点是MS_SHREAD类型的,那么系统中所有namespace中的相等挂载点都属于同一个对等组。另外,通过bind mount得到的挂载点也属于同一个对等组。

关于默认值的争议

因为情况有一点复杂,目前为止,我们都避免讨论传递类型的默认值。对于内核来说,一个新的挂载点被创建时的情况如下:

  • 如果一个挂载点有一个父挂载点,并且父挂载点的类型时MS_SHARED,那么新的挂载点的传递类型也是MS_SHARED。

  • 否则,新的挂载点的类型时MS_PRIVATE。

根据这些规则,根挂载点应该时MS_PRIVATE,这样它的子挂载点默认都是MS_PRIVATE。然而,由于MS_SHARED是更为常用的一种传递类型,所以默认值设为MS_SHARED也更为合理。这样,systemd将所有挂载点的传递类型设为MS_SHARED。 因此,在大多数现代Linux发行版中,默认传递类型实际上是MS_SHARED。但是,还不能就此作结论。当使用ushare()函数创建一个新的命名空间时,会将命名空间内的所有新创建的挂载点的默认值设置为MS_PRIVATE, 如下命令所示,递归的将根目录下的所有挂载点设置为MS_PRIVATE。

640?wx_fmt=png


了防止unshare将默认值设置为MS_PRIVATE,我们可以使用如下命令创建新的命名空间:

640?wx_fmt=png

THE END

本文中,我们讲解了mount namespace和共享子树,大家也可以阅读其他lwn上其他关于namespace的文章。

namespace系列链接:https://lwn.net/Articles/531114/#series_index

原文链接:

https://lwn.net/Articles/689856/


本文来源:Linux内核之旅


查看"Linux阅码场"精华技术文章请移步:

Linux阅码场精华文章汇总


扫描二维码关注"Linux阅码场" 

640?wx_fmt=png

这篇关于黄东升: mount namespace和共享子树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/229101

相关文章

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

# VMware 共享文件

VMware tools快速安装 VMware 提供了 open-vm-tools,这是 VMware 官方推荐的开源工具包,通常不需要手动安装 VMware Tools,因为大多数 Linux 发行版(包括 Ubuntu、CentOS 等)都包含了 open-vm-tools,并且已经优化以提供与 VMware 环境的兼容性和功能支持。 建议按照以下步骤安装 open-vm-tools 而不

未来工作趋势:零工小程序在共享经济中的作用

经济在不断发展的同时,科技也在飞速发展。零工经济作为一种新兴的工作模式,正在全球范围内迅速崛起。特别是在中国,随着数字经济的蓬勃发展和共享经济模式的深入推广,零工小程序在促进就业、提升资源利用效率方面显示出了巨大的潜力和价值。 一、零工经济的定义及现状 零工经济是指通过临时性、自由职业或项目制的工作形式,利用互联网平台快速匹配供需双方的新型经济模式。这种模式打破了传统全职工作的界限,为劳动

Unable to instantiate Action, goodsTypeAction, defined for 'goodsType_findAdvanced' in namespace '/

报错: Unable to instantiate Action, goodsTypeAction,  defined for 'goodsType_findAdvanced' in namespace '/'goodsTypeAction......... Caused by: java.lang.ClassNotFoundException: goodsTypeAction.......

【C++】作用域指针、智能指针、共享指针、弱指针

十、智能指针、共享指针 从上篇文章 【C++】如何用C++创建对象,理解作用域、堆栈、内存分配-CSDN博客 中我们知道,你的对象是创建在栈上还是在堆上,最大的区别就是对象的作用域不一样。所以在C++中,一旦程序进入另外一个作用域,那其他作用域的对象就自动销毁了。这种机制有好有坏。我们可以利用这个机制,比如可以自动化我们的代码,像智能指针、作用域锁(scoped_lock)等都是利用了这种机制。

OpenStack:Glance共享与上传、Nova操作选项解释、Cinder操作技巧

目录 Glance member task Nova lock shelve rescue Cinder manage local-attach transfer backup-export 总结 原作者:int32bit,参考内容 从2013年开始折腾OpenStack也有好几年的时间了。在使用过程中,我发现有很多很有用的操作,但是却很少被提及。这里我暂不直接

基于springboot+vue+uniapp的“共享书角”图书借还管理系统小程序

开发语言:Java框架:springboot+uniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9 系统展示 后台登录界面 管理员功能界面 出借者管理 图书信息管理 图书归还管理 出租收入管理

Nacos Config 配置中心支持配置共享

文章目录 一、什么是配置中心二、Nacos Config2.1 Nacos Config 工作原理 (★)2.2 Nacos Config 的使用2.3 动态刷新2.4 配置共享2.4.1 同一个微服务的不同环境之间共享配置2.4.2 不同微服务中间共享配置 一、什么是配置中心 微服务架构下关于配置文件的存在以下问题: 配置文件相对分散。在一个微服务架构下,配置文件会随

大话C++:第6篇 命名空间namespace作用域

1 命名空间概述 在一个大型的软件项目中,可能会有许多不同的代码文件,这些文件可能由不同的开发者编写,或者来自不同的库和模块。如果这些代码文件中存在同名的变量、函数、类或其他标识符,那么在编译或运行时就可能发生命名冲突,导致程序无法正确执行。 通过使用命名空间(namespace),开发者可以将相关的代码、变量、函数等组织在一起,形成一个独立的命名空间。这样,即使不同的代码片段中使用了相同的标