首页 > 系统相关 >Linux namespace之:mount namespace

Linux namespace之:mount namespace

时间:2023-09-20 23:13:49浏览次数:52  
标签:shared mnt mount namespace iso Linux 挂载


Linux namespace系列文章


理解mount namespace

用户通常使用mount命令来挂载普通文件系统,但实际上mount能挂载的东西非常多,甚至连现在功能完善的Linux系统,其内核的正常运行也都依赖于挂载功能,比如挂载根文件系统/。其实所有的挂载功能和挂载信息都由内核负责提供和维护,mount命令只是发起了mount()系统调用去请求内核。

mount namespace可隔离出一个具有独立挂载点信息的运行环境,内核知道如何去维护每个namespace的挂载点列表。即每个namespace之间的挂载点列表是独立的,各自挂载互不影响

内核将每个进程的挂载点信息保存在/proc/<pid>/{mountinfo,mounts,mountstats}三个文件中:

$ ls -1 /proc/$$/mount*
/proc/26276/mountinfo
/proc/26276/mounts
/proc/26276/mountstats

具有独立的挂载点信息,意味着每个mnt namespace可具有独立的目录层次,这在容器中起了很大作用:容器可以挂载只属于自己的文件系统。

当创建mount namespace时,内核将拷贝一份当前namespace的挂载点信息列表到新的mnt namespace中,此后两个mnt namespace就没有了任何关系(不是真的毫无关系,参考后文shared subtrees)。

创建mount namespace的方式是使用unshare命令的--mount, -m选项:

# 创建mount+uts namespace
# -m或--mount表示创建mount namespace
# 可同时创建具有多种namespace类型的namespace
unshare --mount --uts <program>

下面做一个简单的试验,在root namespace中挂载1.iso文件到/mnt/iso1目录,在新建的mount+uts namespace中挂载2.iso到/mnt/iso2目录:

[~]->$ cd
[~]->$ mkdir iso
[~]->$ cd iso
[iso]->$ mkdir -p iso1/dir1
[iso]->$ mkdir -p iso2/dir2  
[iso]->$ mkisofs -o 1.iso iso1  # 将iso1目录制作成镜像文件1.iso
[iso]->$ mkisofs -o 2.iso iso2  # 将iso2目录制作成镜像文件2.iso
[iso]->$ ls
1.iso  2.iso  iso1  iso2
[iso]->$ sudo mkdir /mnt/{iso1,iso2}
[iso]->$ ls -l /proc/$$/ns/mnt
lrwxrwxrwx 1 ... /proc/26276/ns/mnt -> 'mnt:[4026531840]'

# 在root namespace中挂载1.iso到/mnt/iso1目录
[iso]->$ sudo mount 1.iso /mnt/iso1  
mount: /mnt/iso: WARNING: device write-protected, mounted read-only.
[iso]->$ mount | grep iso1
/home/longshuai/iso/1.iso on /mnt/iso1 type iso9660

# 创建mount+uts namespace
[iso]->$ sudo unshare -m -u /bin/bash
# 虽然这个namespace是mount+uts的namespace
# 但注意mnt namespace和uts namespace的inode并不一样
root@longshuai-vm:/home/longshuai/iso# ls -l /proc/$$/ns
lrwxrwxrwx ... cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx ... ipc -> 'ipc:[4026531839]'
lrwxrwxrwx ... mnt -> 'mnt:[4026532588]'
lrwxrwxrwx ... net -> 'net:[4026531992]'
lrwxrwxrwx ... pid -> 'pid:[4026531836]'
lrwxrwxrwx ... pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx ... user -> 'user:[4026531837]'
lrwxrwxrwx ... uts -> 'uts:[4026532589]'

# 修改主机名为ns1
root@longshuai-vm:/home/longshuai/iso# hostname ns1
root@longshuai-vm:/home/longshuai/iso# exec $SHELL

# 在namespace中,可以看到root namespace中的挂载信息
root@ns1:/home/longshuai/iso# mount | grep 'iso1' 
/home/longshuai/iso/1.iso1 on /mnt/iso1 type iso9660

# namespace中挂载2.iso2
root@ns1:/home/longshuai/iso# mount 2.iso2 /mnt/iso2/
mount: /mnt/iso2: WARNING: device write-protected, mounted read-only.
root@ns1:/home/longshuai/iso# mount | grep 'iso[12]'
/home/longshuai/iso/1.iso1 on /mnt/iso1 type iso9660
/home/longshuai/iso/2.iso2 on /mnt/iso2 type iso9660

# 在namespace中卸载iso1
root@ns1:/home/longshuai/iso# umount /mnt/iso1/
root@ns1:/home/longshuai/iso# mount | grep 'iso[12]' 
/home/longshuai/iso/2.iso2 on /mnt/iso2 type iso9660
root@ns1:/home/longshuai/iso# ls /mnt/iso1/
root@ns1:/home/longshuai/iso# ls /mnt/iso2
dir2

#### 打开另一个Shell终端窗口
# iso1挂载仍然存在,且没有iso2的挂载信息
[iso]->$ mount | grep iso
/home/longshuai/iso/1.iso1 on /mnt/iso1 type iso9660
[iso]->$ ls /mnt/iso2
[iso]->$ ls /mnt/iso1
dir1

以上是mount namespace的基本内容,只有一个关键点:创建mnt namespace时会拷贝当前namespace的挂载点信息,之后两个namespace就没有关系了。

mnt namespace: shared subtrees

Linux的每个挂载点都具有一个决定该挂载点是否共享子挂载点的属性,称为shared subtrees。该属性以决定某挂载点之下新增或移除子挂载点时,是否同步影响它【副本】挂载点。如不了解该属性的作用,参考mount bind和shared subtrees详解

简单说说shared subtrees特性,该特性有什么用呢?以mnt namespace为例来简单介绍一下shared subtrees特性。

假设基于root namespace创建了一个mnt namespace(ns1),那么ns1将具有当前root namespace的挂载点信息拷贝。如果此时新插入了一块磁盘并对其分区格式化,然后在root namespace中对其进行挂载,默认情况下,在ns1中将看不到新挂载的文件系统。这种默认行为可以通过修改shared subtrees属性来改变。

其实,用户创建namespace,其目的一般是希望创建完全隔离的运行环境,所以默认情况下,拷贝挂载点信息时不会拷贝shared subtrees属性,而是将mount namespace中的所有挂载点的shared subtrees属性设置为private。

所以,假如namespace ns1中/mnt/foo是一个挂载点目录,基于ns1创建了一个mnt namespace ns2,在默认情况下:

  • 如果此时在ns1中新增一个挂载点/mnt/foo/bar,将不会影响到ns2中的/mnt/foo
  • 如果此时在ns2中新增一个挂载点/mnt/foo/baz,也不会影响到ns1中的/mnt/foo
  • 移除挂载点操作也一样

但这种默认行为可以改变。

unshare有一个选项--propagation private|shared|slave|unchanged可控制创建mnt namespace时挂载点的共享方式。

  • private:表示新创建的mnt namespace中的挂载点的shared subtrees属性都设置为private,即ns1和ns2的挂载点互不影响
  • shared:表示新创建的mnt namespace中的挂载点的shared subtrees属性都设置为shared,即ns1或ns2中新增或移除子挂载点都会同步到另一方
  • slave:表示新创建的mnt namespace中的挂载点的shared subtrees属性都设置为slave,即ns1中新增或移除子挂载点会影响ns2,但ns2不会影响ns1
  • unchanged:表示拷贝挂载点信息时也拷贝挂载点的shared subtrees属性,也就是说挂载点A原来是shared,在mnt namespace中也将是shared
  • 不指定--progapation选项时,创建的mount namespace中的挂载点的shared subtrees默认值是private

例如:

# root namespace:ns0
$ sudo mount --bind foo bar
$ sudo mount --make-shared bar    # 挂载点设置为shared

# 创建mnt namespace:ns1,且也拷贝shared属性
$ PS1="ns1$ " sudo unshare -m -u --propagation unchanged sh
[ns1]$ grep 'foo' /proc/self/mountinfo 
944 682 8:5 foo bar rw,relatime shared:1

# 在ns1中bar挂载点下新增子挂载点,子挂载点将同步到ns0
# 因为foo和bar已绑定,且bar的属性是shared,所以还会同步到foo目录下
[ns1]$ sudo mount --bind baz bar/subfoo
[ns1]$ tree foo bar 
foo
└── subfoo
    └── subbaz
bar
└── subfoo
    └── subbaz
[ns1]$ grep 'foo' /proc/self/mountinfo
944 682 8:5 foo bar rw,relatime shared:1
945 944 8:5 baz bar/subfoo rw,relatime shared:1
947 682 8:5 baz foo/subfoo rw,relatime shared:1

# 第二个窗口会话中查看ns0的挂载点信息
# 已经同步过来了
$ grep 'foo' /proc/self/mountinfo
622 29 8:5  foo bar rw,relatime shared:1
948 622 8:5 baz bar/subfoo rw,relatime shared:1
946 29 8:5  baz foo/subfoo rw,relatime shared:1
$ tree foo bar 
foo
└── subfoo
    └── subbaz
bar
└── subfoo
    └── subbaz

标签:shared,mnt,mount,namespace,iso,Linux,挂载
From: https://www.cnblogs.com/f-ck-need-u/p/17718768.html

相关文章

  • Linux namespace之:pid namespace
    Linuxnamespace系列文章理解pidnamespacePIDnamespace表示隔离一个具有独立PID的运行环境。在每一个pidnamespace中,进程的pid都从1开始,且和其他pidnamespace中的PID互不影响。这意味着,不同pidnamespace中可以有相同的PID值。因为PIDnamespace中的PID是独立的,每一个PID......
  • Linux namespace之:network namespace
    Linuxnamespace系列文章理解networknamespacenetworknamespace用来隔离网络环境,在networknamespace中,网络设备、端口、套接字、网络协议栈、路由表、防火墙规则等都是独立的。因networknamespace中具有独立的网络协议栈,因此每个networknamespace中都有一个lo接口,但lo接......
  • 测试linux代码运行时间
    1. 前置知识  (1)gettid内核给线程(轻量级进程)分配的进程id,全局(所有进程中)唯一;  (2)pthread_self()是在用户态实现的,获取的是相对于进程的线程控制块的首地址,只是在当前进程空间中是唯一的。不能保证同一进程先后多个线程具有不同的id。(当前一个线程结束其生命周期,进程又新......
  • Linux Namespace
    1LinuxNamespace概述Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。1.1Linux内核支持的namespaces目前,Linux内核里面实现了7种不同类型的......
  • Metasploitable-Linux靶机配置
    Metasploitable和kali是课上下载好的。直接打开进入欢迎界面用默认账号登录了之后,修改root密码(sudopasswdroot),登录root账号,查看本机IP(ifconfig)切换到kali,把kali的IP改为192.168.72.129,且能ping通192.168.72.131在kali的浏览器中输入靶机的IP,可以看到靶机的界面......
  • linux中grep与find的区别,Linux三剑客【grep、sed和awk】
    在使用linux时,经常需要进行文件查找。其中查找的命令主要有find和grep。两个命令是有区的。区别:(1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访问时间,修改时间等。(2)grep是根据文件的内容进行查找,会对文件的每一行按照给定的模式(patter)......
  • linux第四周技术博客
    这周我们学习了Linux的文件的操作之前我们已经在/home目录中创建了/swxy目录我们首先来学习touch命令,用户可以通过touch命令来创建一个空白文件,也可以设置文件属性cd/home/swxytouchabc.txtecho‘abc'>>abc.txt我们可以看到在swxy这个目录中已经创建了abc.txt这个文件,......
  • 1-Linux操作系统 的介绍和安装教程
    一、Linux的介绍1)常见的操作系统Windows,它微软公司开发的一款桌面操作系统(闭源系统)。版本有dos、win98、winNT、winXP、win7、winvista、win8、win10。服务器操作系统:winserver2003、winserver2008、winserver2012。Mac,苹果公司开发的一款操作系统(闭源系统),目前最......
  • linux网络配置
    linux网络配置一:网络配置的相关概念1:网关网关就是连接不同网段的,可以让不同网段的主机进行通信,就相当于是一个网段鹅出口,必须通过这个出口出去,才能与外界进行通信,在linux中有默认的网关,NAT模式中默认的网关就是以.2结尾比如Ip为192.168.10.10它的网关就是192.168.10.2......
  • 《Linux命令行与shell脚本编程大全.第3版》电子书PDF+源代码
    精通Linux命令行与shell脚本编程,尽在本书中本书是关于Linux命令行和shell命令的全面参考资料,涵盖详尽的动手教程和实际应用指南,并提供相关参考信息和背景资料,带你从Linux命令行基础入手,直到写出自己的shell。时隔四年后的这一版本,针对Linux的新特性和实践,进行了全面更新:使用......