Linux Namespace : Mount
Mount namespace 为进程提供独立的文件系统视图。简单点说就是,mount namespace 用来隔离文件系统的挂载点,这样进程就只能看到自己的 mount namespace 中的文件系统挂载点。
进程的 mount namespace 中的挂载点信息可以在 /proc/[pid]/mounts、/proc/[pid]/mountinfo 和 /proc/[pid]/mountstats 这三个文件中找到。
每个 mount namespace 都有一份自己的挂载点列表。当我们使用 clone 函数或 unshare 函数并传入 CLONE_NEWNS 标志创建新的 mount namespace 时, 新 mount namespace 中的挂载点其实是从调用者所在的 mount namespace 中拷贝的。但是在新的 mount namespace 创建之后,这两个 mount namespace 及其挂载点就基本上没啥关系了(除了 shared subtree 的情况),两个 mount namespace 是相互隔离的。
本文我们将通过 demo 演示如何对通过 mount namespace 对文件系统进行隔离,以及 shared subtree 在 mount namespace 中的使用方式。本文的演示环境为 ubuntu 16.04。
演示文件系统的隔离
我们通过 iso 文件的挂载来演示 mount namespace 对文件系统的隔离。下面先创建演示用的文件和目录:
$ sudo mkdir /demo && sudo chmod /demo && cd $_
$ mkdir -p iso1/subdir1
$ mkdir -p iso2/subdir2
$ mkisofs -o .iso ./iso1
$ mkisofs -o .iso ./iso2

然后再准备两个充当挂载点:
$ sudo mkdir /mnt/iso1 /mnt/iso2
第一步,我们打开两个 bash shell,为了方便区分,分别把它们称为为 shell1 和 shell2。在 shell1 中执行挂载操作,把 1.iso 挂载到 /mnt/iso1 目录:
$ sudo mount .iso /mnt/iso1

第二步,先在 shell2 中执行 sudo unshare -m,然后在两个 shell 中分别执行 readlink /proc/$$/ns/mnt 命令:

图中左侧为 shell1,右侧为 shell2。可以看出它们的 mount namespace 是不同的。
第三步,通过 mount 命令查看两个 mount namespace 中的挂载点信息:

此时,在这两个 mount namespace 中,挂载点信息是相同的。
第四步,我们在 shell2 中执行一些 mount 和 umount 操作:
$ mount .iso /mnt/iso2
$ umount /mnt/iso1

再查之下发现两个 mount namespace 中的挂载点信息已经完全不一样了,这就说明 mount namespace 之间的挂载点信息是隔离的(也就是文件系统是隔离的)。
演示 shared subtree 功能
Mount namespace 实现了挂载点的隔离,但对于某些应用场景,会让我们用起来很不爽。比如系统新添加了一个磁盘设备,我们打算让所有的 mount namespace 都挂载它。过去的做法只能是在每个 mount namespace 中都挂载一遍,很显然,这太不方便了。于是在 Linux 内核 2.6.15 引入了 shared subtree 的概念来解决这个问题。Shared subtree 的核心是允许在 mount namespace 之间自动地或者是受控地传播 mount 和 umount 事件。
简单起见,本文只演示 shared subtree 中 shared 和 private 两种传播类型在 mount namespace 中的表现。我们可以简单的认为 shared 类型的传播方式可以在满足条件的情况下把 mount 和 umount 事件传播给其它的挂载点,而 private 类型的传播方式则不会把 mount 和 umount 事件传播给其它的挂载点。关于 shared subtree 的详细内容,请参考 shared subtree 文档。关于 shared subtree 与 mount namespace 结合使用的详细信息,请参考 mount namespace 文档。
我们通过虚拟磁盘文件的挂载来演示 shared subtree 在 mount namespace 中的表现。下面先创建演示用的文件和目录:
$ sudo mkdir /demo && sudo chmod /demo && cd $_
$ dd if=/dev/zero bs=1M count= of=./disk1.img
$ dd if=/dev/zero bs=1M count= of=./disk2.img
$ dd if=/dev/zero bs=1M count= of=./disk3.img
$ dd if=/dev/zero bs=1M count= of=./disk4.img
$ mkfs.ext2 ./disk1.img
$ mkfs.ext2 ./disk2.img
$ mkfs.ext2 ./disk3.img
$ mkfs.ext2 ./disk4.img
$ mkdir disk1 disk2

第一步,我们打开两个 bash shell,为了方便区分,分别把它们称为为 shell1 和 shell2。在 shell1 中执行挂载操作,分别以 shared 和 private 方式挂载 disk1 和 disk2:
$ sudo mount --make-shared disk1.img ./disk1
$ sudo mount --make-private disk2.img ./disk2
第二步,在 shell2 中执行 sudo unshare -m --propagation unchanged,然后在两个 shell 中分别执行 readlink /proc/$$/ns/mnt 命令:

图中左侧为 shell1,右侧为 shell2。可以看出它们的 mount namespace 是不同的。默认情况下,unshare 会将新 namespace 里面的所有挂载点的类型设置成 private,所以我们使用参数 --propagation unchanged 让新 namespace 里的挂载点的类型和老 namespace 里保持一致。--propagation 参数还支持 private|shared|slave 类型,和 mount 命令的那些 --make-private 参数一样,它们实际上都是通过调用 mount 函数并传入不同的参数实现的。
第三步,分别在 shell1 和 shell2 中执行 cat /proc/self/mountinfo |grep disk| sed 's/ - .*//' 命令查看挂载点信息:

此时两个 mount namespace 中的挂载点信息是相同的。由于在挂载 /demo/disk1 时应用了 --make-shared 参数,所以上图 shell1 中 /demo/disk1 的挂载方式显示为 shared。又因为在 shell2 中执行 unshare 命令时设置了 --propagation unchanged 参数,所以上图中 shell2 中 /demo/disk1 的挂载方式也显示为 shared(*不设置 --propagation unchanged 参数则为 private 方式*)。
第四步,在 shell2 中分别在 disk1 目录下创建 disk3 目录,在 disk2 目录下创建 disk4 目录,并把 disk3.img 挂载到 ./disk1/disk3 目录,把 disk4.img 挂载到 ./disk2/disk4 目录:
$ mkdir ./disk1/disk3 ./disk2/disk4
$ mount disk3.img ./disk1/disk3
$ mount disk4.img ./disk2/disk4
然后使用分别在 shell1 和 shell2 中使用 cat /proc/self/mountinfo |grep disk| sed 's/ - .*//' 命令查看挂载点信息:

这次 shell1 中的挂载点信息和 shell2 中的挂载点信息是不一样的。因为 /demo/disk1 的挂载方式为 shared,所以它的子挂载点 /demo/disk1/disk3 被传播到了 shell1 所在的 mount namespace 中。而 /demo/disk2 的挂载方式为 private,所以它的子挂载点 /demo/disk2/disk4 不会被传播。
OK,这就完成了 shared subtree 在 mount namespace 间传播挂载点信息的基本功能演示,希望这个小 demo 可以帮助大家了解一点 shared subtree 相关的内容。
总结
要把 mount namespace 介绍清楚显然不是本文的目的,因为单是 shared subtree 在 mount namespace 中的使用方式就够我们好好的研究一番了。所以,本文只是希望以最少的概念加上最简单的 demo 来说明什么是 mount namespace、它可以用来干什么以及如何快速的实验一下。
参考:
Linux Namespace系列(04):mount namespaces (CLONE_NEWNS)
Linux Namespace分析——mnt namespace的实现与应用
Mount namespace man page
Applying mount namespaces
Linux Namespace : Mount的更多相关文章
- 理解Docker(3):Docker 使用 Linux namespace 隔离容器的运行环境
本系列文章将介绍Docker的有关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...
- Docker之Linux Namespace
Linux Namespace 介绍 我们经常听到说Docker 是一个使用了Linux Namespace 和 Cgroups 的虚拟化工具,但是什么是Linux Namespace 它在Docke ...
- Docker基础技术:Linux Namespace(下)
在 Docker基础技术:Linux Namespace(上篇)中我们了解了,UTD.IPC.PID.Mount 四个namespace,我们模仿Docker做了一个相当相当山寨的镜像.在这一篇中,主 ...
- Docker基础技术:Linux Namespace(上)
时下最热的技术莫过于Docker了,很多人都觉得Docker是个新技术,其实不然,Docker除了其编程语言用go比较新外,其实它还真不是个新东西,也就是个新瓶装旧酒的东西,所谓的The New “O ...
- Docker 基础技术:Linux Namespace(下)
导读 在Docker基础技术:Linux Namespace(上篇)中我们了解了,UTD.IPC.PID.Mount 四个namespace,我们模仿Docker做了一个相当相当山寨的镜像.在这一篇中 ...
- Docker 基础技术之 Linux namespace 详解
Docker 是"新瓶装旧酒"的产物,依赖于 Linux 内核技术 chroot .namespace 和 cgroup.本篇先来看 namespace 技术. Docker 和虚 ...
- Docker 基础技术之 Linux namespace 源码分析
上篇我们从进程 clone 的角度,结合代码简单分析了 Linux 提供的 6 种 namespace,本篇从源码上进一步分析 Linux namespace,让你对 Docker namespace ...
- Linux Namespace : UTS
UTS namespace 用来隔离系统的 hostname 以及 NIS domain name.UTS 据称是 UNIX Time-sharing System 的缩写. hostname 与 N ...
- Linux Namespace : 简介
在初步的了解 docker 后,笔者期望通过理解 docker 背后的技术原理来深入的学习和使用 docker,接下来的几篇文章简单的介绍下 linux namespace 的概念以及基本用法. na ...
随机推荐
- postman测试方法的 时候总是出现状态码500
postman测试方法的 时候总是出现状态码500 { "timestamp": "2018-07-23T05:43:51.773+0000", ...
- MySQL 基本语句(1)
一.cmd命令行的常用命令: 当我们使用MySQL 5.5 Command Line Client这个客户端登陆时,只能登陆root用户.如果今后创建了别的用户,就很麻烦了,所以我们不用MySQL 5 ...
- python数据类型分类以及运算类型
一.python数据类型 目录: 1.数字(整数.小数) 2.字符串(单引号.双引号.三引号) 3.元组 #元素确定之后不能修改 4.列表 #元素可以修改 5.集合 #不讲顺序,得到的结果没有重复元 ...
- Jenkins系统监测
Jenkins 是一个开源项目,提供了一种易于使用的持续集成系统,使开发者从繁杂的集成中解脱出来,专注于更为重要的业务逻辑实现上.同时 Jenkins 能实施监控集成中存在的错误,提供详细的日志文件和 ...
- Windows重启显卡驱动热键说明
Windows 有一个秘密的快捷键,可以重启显卡驱动程序.如果你的电脑经常“冻屏”,可以在重启电脑之前试试这个快捷键,它可以修复冻屏,否则就只能强制重启电脑了. 这个组合快捷键将重启 Win10 和 ...
- java基础学习总结——equals方法
一.equals方法介绍 1.1.通过下面的例子掌握equals的用法 package cn.galc.test; public class TestEquals { public static vo ...
- 设置Linux环境变量的方法和区别_Ubuntu
设置 Linux 环境变量可以通过 export 实现,也可以通过修改几个文件来实现,有必要弄清楚这两种方法以及这几个文件的区别. 通过文件设置 Linux 环境变量 首先是设置全局环境变量,对所有用 ...
- Ubuntu16.04下iTop4412环境搭建+Android4.0.3编译
系统:Ubuntu16.04.02(优麒麟) 安装库文件和JDK 使用cd 命令,进入解压出来的“Android_JDK” -->“jdk6”文件夹,运行脚本文件 “install-sun-ja ...
- May 30. 2018 Week 22nd Wednesday
Never forget to say "Thanks." 永远不要忘记说谢谢. Don't take anything we get for granted, and never ...
- 在Ubuntu 12.04下创建eclipse的桌面链接
在Ubuntu 12.04下创建eclipse的桌面链接 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 在Ubuntu 12.04上安装Hadoop并 ...