文章目录
- [1. 基础准备](#1. 基础准备)
-
- [1.1 dd 命令详解与镜像创建](#1.1 dd 命令详解与镜像创建)
- [1.2 mkfs 命令与文件系统格式化](#1.2 mkfs 命令与文件系统格式化)
-
- [1.2.1 为什么要格式化?](#1.2.1 为什么要格式化?)
- [1.3 df命令详解](#1.3 df命令详解)
- [1.4 mount 命令与磁盘挂载原理](#1.4 mount 命令与磁盘挂载原理)
-
- [1.4.1 U盘类比](#1.4.1 U盘类比)
- [1.5 unshare 命令概览](#1.5 unshare 命令概览)
- [2. PID 隔离实战](#2. PID 隔离实战)
-
- [2.1 PID 隔离实验操作](#2.1 PID 隔离实验操作)
- [3. Mount 隔离与文件系统视图](#3. Mount 隔离与文件系统视图)
- [4. 思维导图](#4. 思维导图)
1. 基础准备
1.1 dd 命令详解与镜像创建
dd(Data Duplicator): 这是一个底层的命令行工具,用于在Linux系统上读取、转换并输出原始数据。它可以直接操作字节流,因此常用于备份分区、销毁数据或创建指定大小的空文件(镜像)。
dd可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。在
Linux中,最常用于创建、转换和拷贝原始数据的工具就是dd命令。
语法:
shell
dd OPTION
参数 :
if=文件名:输入文件名,默认为标准输入。即指定源文件。
of=文件名:输出文件名,默认为标准输出。即指定目的文件。
ibs=bytes:一次读入 bytes 个字节,即指定一个块大小为 bytes 个字节。
obs=bytes:一次输出 bytes 个字节,即指定一个块大小为 bytes 个字节。
bs=bytes:同时设置读入/输出的块大小为 bytes 个字节。
cbs=bytes:一次转换 bytes 个字节,即指定转换缓冲区大小。
skip=blocks:从输入文件开头跳过 blocks 个块后再开始复制。
seek=blocks:从输出文件开头跳过 blocks 个块后再开始复制。
count=blocks:仅拷贝 blocks 个块,块大小等于 ibs 指定的字节数。
conv=<关键字>,关键字可以有以下 11 种:
conversion:用指定的参数转换文件。ascii:转换 ebcdic 为 asciiebcdic:转换 ascii 为 ebcdicibm:转换 ascii 为 alternate ebcdicblock:把每一行转换为长度为 cbs,不足部分用空格填充unblock:使每一行的长度都为 cbs,不足部分用空格填充lcase:把大写字符转换为小写字符ucase:把小写字符转换为大写字符swap:交换输入的每对字节noerror:出错时不停止notrunc:不截短输出文件sync:将每个输入块填充到 ibs 个字节,不足部分用空(NUL)字符补齐。
--help:显示帮助信息
--version:显示版本信息
- 数据量计算: 最终生成文件的大小 =
bs×count。/dev/zero: 这是一个特殊的设备文件,它会提供无限的空字符(NULL),常作为if来创建空镜像。
示例:创建一个 8,80MB 的磁盘镜像
shell
# 创建一个名为 testns 的新目录
root@yudukai:~# mkdir testns
# 进入 testns 目录
root@yudukai:~# cd testns
# 查看当前目录的详细信息
# total 0 表示目录为空
root@yudukai:~/testns# ls -l
total 0
# 使用 dd 命令创建一个8MB的测试文件
# if=/dev/zero:输入文件为 /dev/zero(生成全0字节)
# of=test.img:输出文件名为 test.img
# bs=8k:块大小为8KB
# count=1024:复制1024个块
# 总大小 = 8KB × 1024 = 8MB
root@yudukai:~/testns# dd if=/dev/zero of=test.img bs=8k count=1024
1024+0 records in # 读入1024个记录
1024+0 records out # 写出1024个记录
8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.00944598 s, 888 MB/s
# 文件大小8MB,耗时约0.009秒,速度888 MB/s
# 以人类可读格式查看文件信息
root@yudukai:~/testns# ll -h
total 8.1M
drwxr-xr-x 2 root root 4.0K Jul 29 18:14 ./
drwx------ 15 root root 4.0K Jul 29 18:13 ../
-rw-r--r-- 1 root root 8.0M Jul 29 18:14 test.img
# 可以看到 test.img 文件大小为 8.0M
# 使用 dd 命令创建一个80MB的测试文件
# 总大小 = 8KB × 10240 = 80MB
root@yudukai:~/testns# dd if=/dev/zero of=test2.img bs=8k count=10240
10240+0 records in
10240+0 records out
83886080 bytes (84 MB, 80 MiB) copied, 0.0827256 s, 1.0 GB/s
# 文件大小80MB,耗时约0.083秒,速度1.0 GB/s
# 查看目录中的所有文件
root@yudukai:~/testns# ll -h
total 89M
drwxr-xr-x 2 root root 4.0K Jul 29 18:14 ./
drwx------ 15 root root 4.0K Jul 29 18:13 ../
-rw-r--r-- 1 root root 80M Jul 29 18:14 test2.img # 80MB文件
-rw-r--r-- 1 root root 8.0M Jul 29 18:14 test.img # 8MB文件
shell
# 使用 vi 编辑器创建一个名为 in.txt 的文件
root@yudukai:~/testns# vi in.txt
# 在 vi 中输入了内容 "Hello World" 并保存退出
# 使用 dd 命令将 in.txt 转换为大写并输出到 out.txt
# if=in.txt:输入文件为 in.txt
# of=out.txt:输出文件为 out.txt
# conv=ucase:转换选项,将小写字母转换为大写字母(uppercase)
root@yudukai:~/testns# dd if=in.txt of=out.txt conv=ucase
0+1 records in # 读入0+1个记录(不满一个块)
0+1 records out # 写出0+1个记录
12 bytes copied, 0.000178502 s, 67.2 kB/s
# 共复制了12字节("Hello World\n",含换行符)
# 查看 in.txt 文件内容
root@yudukai:~/testns# cat in.txt
Hello World
# 查看 out.txt 文件内容(已全部转为大写)
root@yudukai:~/testns# cat out.txt
HELLO WORLD
1.2 mkfs 命令与文件系统格式化
mkfs(Make Filesystem): 这是一个用于在设备(或镜像文件)上建立Linux文件系统的命令。它会在磁盘空间内构建必要的数据结构,如Superblock(超级块)、Inode列表和数据块区。
在Linux中,刚创建的镜像文件就像一张白纸,虽然有了空间,但没有"格子"和"页码"。为了让操作系统能够管理文件、目录和权限,我们需要对其进行格式化。
语法:
shell
mkfs [-V] [-t fstype] [fs-options] filesys [blocks]
参数:
-t fstype:指定要建立何种文件系统;如ext3,ext4filesys:指定要创建的文件系统对应的设备文件名;blocks:指定文件系统的磁盘块数。-V: 详细显示模式fs-options:传递给具体的文件系统的参数
1.2.1 为什么要格式化?
dd创建的镜像: 像是一本刚从造纸厂出来的、没有任何线条的空白本子。虽然它有厚度(空间),但你很难整齐地书写信息,事后也很难查找某个特定的段落。mkfs格式化后: 相当于给这本本子画上了行线、印上了页码,并预留了目录页 。有了这些结构,操作系统(读者)就能根据目录(Inode)快速找到对应的文字内容(Data Block)。在
Namespace隔离实战中,只有经过格式化的镜像,才能被mount命令识别并挂载到文件系统中,作为一个独立的"小世界"存在。
mkfs实际上是一系列命令的通用前端。当你执行格式化时,它会根据你指定的类型调用对应的程序(如mkfs.ext4或mkfs.xfs)在
Linux容器技术中,ext4是最常用的日志文件系统之一,它稳定且支持各种高级特性。
示例:
shell
# 在 test.img 文件上创建 ext4 类型的文件系统
# -t ext4:指定文件系统类型为 ext4
# ./test.img:目标文件(之前创建的8MB空文件)
root@yudukai:~/testns# mkfs -t ext4 ./test.img
mke2fs 1.46.5 (30-Dec-2021) # mke2fs 工具版本信息
Discarding device blocks: done # 丢弃设备块(针对虚拟设备的优化)
Creating filesystem with 2048 4k blocks and 2048 inodes# 创建文件系统信息:
# - 2048 个 4KB 块 = 2048 × 4KB = 8MB 总大小
# - 2048 个 inode(索引节点,用于存储文件元数据)
Allocating group tables: done # 分配组表(文件系统结构)
Writing inode tables: done # 写入 inode 表
Creating journal (1024 blocks): done# 创建日志(1024个块,用于数据安全恢复)
Writing superblocks and filesystem accounting information: done# 写入超级块和文件系统统计信息
root@yudukai:~/testns#
1.3 df命令详解
Linux df(英文全拼:disk free) 命令用于显示目前在Linux系统上的文件系统磁盘使用情况统计。
语法:
shell
df [OPTION]... [FILE]...
常见参数
-a,--all:包含所有的具有0Blocks的文件系统-h,--human-readable:使用人类可读的格式(预设值是不加这个选项的...)-H,--si:很像-h, 但是用1000为单位而不是用1024-t,--type=TYPE:限制列出文件系统的TYPE-T,--print-type:显示文件系统的形式
案例:
shell
root@yudukai:~/testns# df
Filesystem 1K-blocks Used Available Use% Mounted on
tmpfs 814028 79784 734244 10% /run
/dev/vda1 185458052 25534852 151950328 15% /
tmpfs 4070132 0 4070132 0% /dev/shm
tmpfs 5120 0 5120 0% /run/lock
tmpfs 814024 0 814024 0% /run/user/0
root@yudukai:~/testns# df -a
Filesystem 1K-blocks Used Available Use% Mounted on
sysfs 0 0 0 - /sys
proc 0 0 0 - /proc
udev 4012160 0 4012160 0% /dev
devpts 0 0 0 - /dev/pts
tmpfs 814028 79784 734244 10% /run
/dev/vda1 185458052 25534852 151950328 15% /
securityfs 0 0 0 - /sys/kernel/security
tmpfs 4070132 0 4070132 0% /dev/shm
tmpfs 5120 0 5120 0% /run/lock
cgroup2 0 0 0 - /sys/fs/cgroup
pstore 0 0 0 - /sys/fs/pstore
bpf 0 0 0 - /sys/fs/bpf
systemd-1 - - - - /proc/sys/fs/binfmt_misc
mqueue 0 0 0 - /dev/mqueue
hugetlbfs 0 0 0 - /dev/hugepages
debugfs 0 0 0 - /sys/kernel/debug
tracefs 0 0 0 - /sys/kernel/tracing
fusectl 0 0 0 - /sys/fs/fuse/connections
configfs 0 0 0 - /sys/kernel/config
none 0 0 0 - /run/credentials/systemd-sysusers.service
binfmt_misc 0 0 0 - /proc/sys/fs/binfmt_misc
tracefs 0 0 0 - /sys/kernel/debug/tracing
tmpfs 814024 0 814024 0% /run/user/0
root@yudukai:~/testns# df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 795M 78M 718M 10% /run
/dev/vda1 177G 25G 145G 15% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 795M 0 795M 0% /run/user/0
root@yudukai:~/testns# df -H
Filesystem Size Used Avail Use% Mounted on
tmpfs 834M 82M 752M 10% /run
/dev/vda1 190G 27G 156G 15% /
tmpfs 4.2G 0 4.2G 0% /dev/shm
tmpfs 5.3M 0 5.3M 0% /run/lock
tmpfs 834M 0 834M 0% /run/user/0
root@yudukai:~/testns# df -Th
Filesystem Type Size Used Avail Use% Mounted on
tmpfs tmpfs 795M 78M 718M 10% /run
/dev/vda1 ext4 177G 25G 145G 15% /
tmpfs tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs tmpfs 795M 0 795M 0% /run/user/0
root@yudukai:~/testns#
1.4 mount 命令与磁盘挂载原理
在
Linux的世界里,有一个非常迷人的哲学:一切皆文件 。即使我们刚刚创建并格式化了一个80MB的虚拟磁盘fdimage.img,如果你直接用文本编辑器打开它,你看到的只会是一堆乱码。要真正像访问普通文件夹那样去读写它,我们需要执行"挂载(
Mount)"操作。
挂载 (Mounting): 是指将一个存储设备(如硬盘分区、镜像文件)的内容连接到Linux系统目录树中的某个特定目录(称为挂载点)的过程。一旦挂载成功,该目录就成了进入该存储设备的"入口"。
1.4.1 U盘类比
我们可以把挂载想象成在电脑上插 U 盘:
- 镜像文件 (fdimage.img): 就像是一个物理 U 盘。虽然你手里拿着它,但如果不把它插进接口,你无法查看里面的数据。
- 挂载点 (Mount Point): 就像是电脑上的 USB 接口(或路径) 。在 Linux 中,这通常是一个空的文件夹(如
/data/tmpmount)。- 执行
mount: 就像是把 U 盘插入接口。动作完成后,你访问那个文件夹,实际上就是在读写这个虚拟镜像里的内容。
mount的作用:通过
mount,我们可以把这个镜像挂载到特定的Namespace中,让在该空间运行的进程只能看到这个镜像里的文件,从而实现文件系统的完全隔离。
语法:
shell
mount [-l]
mount [-t vfstype] [-o options] device dir
常见参数:
-l:显示已加载的文件系统列表;-t:加载文件系统类型支持常见系统类型的ext3,ext4,iso9660,tmpfs,xfs等,大部分情况可以不指定,mount可以自己识别-o options:主要用来描述设备或档案的挂接方式。
loop:用来把一个文件当成硬盘分区挂接上系统ro:采用只读方式挂接设备rw:采用读写方式挂接设备device:要挂接(mount)的设备。dir:挂载点的目录
案例:
shell
root@yudukai:~/testns# ll
total 86144
drwxr-xr-x 2 root root 4096 Jul 29 18:16 ./
drwx------ 15 root root 4096 Jul 29 18:15 ../
-rw-r--r-- 1 root root 12 Jul 29 18:15 in.txt
-rw-r--r-- 1 root root 12 Jul 29 18:16 out.txt
-rw-r--r-- 1 root root 83886080 Jul 29 18:14 test2.img
-rw-r--r-- 1 root root 8388608 Jul 29 18:18 test.img
# 再次对 test.img 进行 ext4 文件系统格式化
# 注意:系统检测到该文件已包含一个 ext4 文件系统,并询问是否继续
root@yudukai:~/testns# mkfs -t ext4 ./test.img
mke2fs 1.46.5 (30-Dec-2021)
./test.img contains a ext4 file system
created on Wed Jul 29 18:18:39 2026
Proceed anyway? (y,N) y
Discarding device blocks: done
Creating filesystem with 2048 4k blocks and 2048 inodes
Allocating group tables: done
Writing inode tables: done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done
# 创建挂载目录
# -p 参数确保父目录 /data 不存在时会自动创建
root@yudukai:~/testns# mkdir -p /data/testmymount
root@yudukai:~/testns# ll /data/testmymount/
total 8
drwxr-xr-x 2 root root 4096 Jul 29 18:42 ./
drwxr-xr-x 3 root root 4096 Jul 29 18:42 ../
# 将 test.img 挂载到 /data/testmymount
# 此时系统会自动使用 loop 设备(/dev/loop0)来挂载这个镜像文件
root@yudukai:~/testns# mount ./test.img /data/testmymount/
# 查看磁盘空间,确认挂载成功
root@yudukai:~/testns# df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 795M 78M 718M 10% /run
/dev/vda1 177G 25G 145G 15% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 795M 0 795M 0% /run/user/0
/dev/loop0 3.5M 24K 3.0M 1% /data/testmymount
# 可以看到 loop0 设备大小为 3.5M(8MB镜像扣除元数据后的实际可用空间较小)
# 这里显示 3.5M 是因为 8MB 空间很大一部分被日志(4MB)和元数据占用了
# 进入挂载目录
root@yudukai:~/testns# cd /data/testmymount/
# 写入字符串 "123" 到 test.txt 文件
root@yudukai:/data/testmymount# echo "123" > test.txt
root@yudukai:/data/testmymount# ll -h
total 28K
drwxr-xr-x 3 root root 4.0K Jul 29 18:43 ./
drwxr-xr-x 3 root root 4.0K Jul 29 18:42 ../
drwx------ 2 root root 16K Jul 29 18:42 lost+found/ # ext4 自动创建的恢复目录
-rw-r--r-- 1 root root 4 Jul 29 18:43 test.txt # 新创建的文件
root@yudukai:/data/testmymount# cat test.txt
123
root@yudukai:/data/testmymount#
1.5 unshare 命令概览
unshare: 顾名思义,它的作用是"不共享"。它允许一个进程与其父进程脱离关系,不再共享某些指定的命名空间(Namespace),从而拥有自己独立的运行环境。
- 默认情况下: 你和你的父进程(比如当前的
Shell)生活在同一个"空间"里。你改了主机名,它也能看到;你挂载了磁盘,它也跟着变。- 执行
unshare后: 你瞬间开启了一个平行空间 。在这个空间里,你可以随意修改系统设置(如网络、进程ID、挂载点),而原本那个空间(父进程所在的空间)对此一无所知,完全不受影响。
语法:
shell
unshare [options] program [arguments]
参数:
-i, --ipc:不共享IPC空间-m, --mount:不共享Mount空间-n, --net:不共享Net空间-p, --pid:不共享PID空间-u, --uts:不共享UTS空间-U, --user:不共享用户-V, --version:版本查看--fork:执行unshare的进程fork一个新的子进程,在子进程里执行unshare传入的参数。--mount-proc:执行子进程前,将proc优先挂载过去
案例:
shell
# 创建新的 UTS 命名空间并在其中运行 /bin/bash
# -u 参数表示创建新的 UTS 命名空间
root@yudukai:/data/testmymount# unshare -u /bin/bash
# 此时进入了一个隔离的 shell 环境,拥有独立的 hostname
# 在新命名空间中修改主机名
root@yudukai:/data/testmymount# hostname test1
# 这里的修改只影响当前命名空间,不影响宿主机
# 在新命名空间中查看主机名
root@yudukai:/data/testmymount# hostname
test1
# 显示的是新设置的主机名(仅在当前命名空间内有效)
# 退出命名空间
root@yudukai:/data/testmymount# exit
exit
# 退出后回到原来的命名空间(宿主机环境)
# 在原命名空间中查看主机名
root@yudukai:/data/testmymount# hostname
yudukai
# 显示原来的主机名,证明刚才的修改没有影响宿主机

- 在执行
exit之前,你在隔离Shell里看到的是新名字。- 执行
exit后,你会发现宿主机的主机名完全没有变化。
通过这个实验,我们成功验证了UTS Namespace的隔离能力。虽然进程依然运行在同一台物理机器和同一个内核上,但通过
Namespace,我们为进程营造了一个"我拥有独立主机名"的假象。这是容器能够拥有独立身份标识的基础。
2. PID 隔离实战
2.1 PID 隔离实验操作
PID(Process ID)Namespace的作用是隔离进程ID空间。在不同的PID命名空间里,可以有相同的PID。这也是为什么每个容器都可以有一个PID为1的init进程,而互不干扰。
--fork参数: 告诉unshare命令创建一个新的子进程(Fork),并让这个子进程 进入新的PID
主机A
shell
root@yudukai:/data/testmymount# unshare -p /bin/bash
bash: fork: Cannot allocate memory # 直接运行 unshare --pid /bin/bash,内核会尝试让当前的 unshare 进程进入新空间,这违反了内核规则,通常会导致报错:Cannot allocate memory(无法分配内存)
root@yudukai:/data/testmymount# exit
exit
root@yudukai:/data/testmymount# unshare -p --fork /bin/bash
root@yudukai:/data/testmymount#
主机B
shell
ps -ef
主机A
shell
ps -ef

然后主机A
shell
root@yudukai:/data/testmymount# exit
exit
root@yudukai:/data/testmymount# unshare -p --fork --mount-proc /bin/bash
如果你只是开启了
PID Namespace而不处理/proc,新创建的子进程依然会沿用宿主机的/proc挂载点。这意味着,虽然你的进程在内核里确实被隔离了,但ps工具由于读取的是旧的"窗口",依然会把宿主机的进程全部显示出来。
--mount-proc: 这个参数会在进入新Namespace的同时,自动为我们重新挂载一个只属于当前Namespace的/proc文件系统。这样,ps就只能看到当前空间内的进程了。使用
--mount-proc时,内核并不是创建了一个新的文件夹,而是为当前PID Namespace提供了一个定制化的接口 。这个接口会过滤掉不属于该Namespace的所有进程信息。
执行后,主机A:
shell
root@yudukai:/data/testmymount# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 19:17 pts/0 00:00:00 /bin/bash
root 9 1 0 19:17 pts/0 00:00:00 ps -ef
root@yudukai:/data/testmymount#
主机B:
一堆进程

3. Mount 隔离与文件系统视图
设备A
shell
root@yudukai:/data/testmymount# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 177G 25G 145G 15% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 795M 78M 718M 10% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 795M 0 795M 0% /run/user/0
/dev/loop0 3.5M 28K 3.0M 1% /data/testmymount
root@yudukai:/data/testmymount# exit
exit
root@yudukai:/data/testmymount#
root@yudukai:/data/testmymount# unshare --fork --mount /bin/bash
root@yudukai:/data/testmymount# ll -h
total 28K
drwxr-xr-x 3 root root 4.0K Jul 29 18:43 ./
drwxr-xr-x 3 root root 4.0K Jul 29 18:42 ../
drwx------ 2 root root 16K Jul 29 18:42 lost+found/
-rw-r--r-- 1 root root 4 Jul 29 18:44 test.txt
root@yudukai:/data/testmymount# dd if=/dev/zero of=data2.img bs=8k count=10240
dd: error writing 'data2.img': No space left on device
423+0 records in
422+0 records out
3457024 bytes (3.5 MB, 3.3 MiB) copied, 0.00879398 s, 393 MB/s
root@yudukai:/data/testmymount# ls -l
total 3400
-rw-r--r-- 1 root root 3457024 Jul 29 19:22 data2.img
drwx------ 2 root root 16384 Jul 29 18:42 lost+found
-rw-r--r-- 1 root root 4 Jul 29 18:44 test.txt
root@yudukai:/data/testmymount# mkfs -t ext4 ./data2.img
mke2fs 1.46.5 (30-Dec-2021)
Filesystem too small for a journal
Discarding device blocks: done
Creating filesystem with 844 4k blocks and 848 inodes
Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
root@yudukai:/data/testmymount# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 177G 25G 145G 15% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 795M 78M 718M 10% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 795M 0 795M 0% /run/user/0
/dev/loop0 3.5M 188K 2.8M 7% /data/testmymount
root@yudukai:/data/testmymount# mkdir -p /data/maxhou/data2mount
root@yudukai:/data/testmymount# ll
total 188
drwxr-xr-x 3 root root 4096 Jul 29 19:22 ./
drwxr-xr-x 4 root root 4096 Jul 29 19:24 ../
-rw-r--r-- 1 root root 3457024 Jul 29 19:23 data2.img
drwx------ 2 root root 16384 Jul 29 18:42 lost+found/
-rw-r--r-- 1 root root 4 Jul 29 18:44 test.txt
root@yudukai:/data/testmymount# ll /data/maxhou/data2mount
total 8
drwxr-xr-x 2 root root 4096 Jul 29 19:24 ./
drwxr-xr-x 3 root root 4096 Jul 29 19:24 ../
root@yudukai:/data/testmymount# mount -t ext4 ./data2.img /data/maxhou/data2mount
root@yudukai:/data/testmymount# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 177G 25G 145G 15% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 795M 78M 718M 10% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 795M 0 795M 0% /run/user/0
/dev/loop0 3.5M 188K 2.8M 7% /data/testmymount
/dev/loop1 3.1M 24K 2.9M 1% /data/maxhou/data2mount
root@yudukai:/data/testmymount# cd /data/maxhou/data2mount/
root@yudukai:/data/maxhou/data2mount# echo "hello test"> test.txt
root@yudukai:/data/maxhou/data2mount# ll
total 28
drwxr-xr-x 3 root root 4096 Jul 29 19:27 ./
drwxr-xr-x 3 root root 4096 Jul 29 19:24 ../
drwx------ 2 root root 16384 Jul 29 19:23 lost+found/
-rw-r--r-- 1 root root 11 Jul 29 19:27 test.txt
root@yudukai:/data/maxhou/data2mount# cat test.txt
hello test
root@yudukai:/data/maxhou/data2mount#
设备B
shell
root@yudukai:/data/testmymount# df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 795M 78M 718M 10% /run
/dev/vda1 177G 25G 145G 15% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 795M 0 795M 0% /run/user/0
/dev/loop0 3.5M 188K 2.8M 7% /data/testmymount
root@yudukai:/data/testmymount# ll /data/maxhou/data2mount/test.txt
ls: cannot access '/data/maxhou/data2mount/test.txt': No such file or directory
root@yudukai:/data/testmymount#
执行
unshare --fork --mount /bin/bash时,内核为设备A复制了一份当前的挂载点信息,但此后设备A的任何挂载操作都是私有的。
- 设备
A的视角: 你执行了mount -t ext4 ./data2.img /data/maxhou/data2mount。内核将这个新的挂载信息记录在了设备A的私有挂载表中。因此,执行df -h时,你能看到/dev/loop1成功挂载。- 设备
B的视角: 宿主机的挂载表没有任何变化。在它的认知里,/data/maxhou/data2mount仅仅是一个普通目录。- 在设备
A中: 执行echo "hello test" > test.txt。这个文件实际上被写进了data2.img这个文件系统镜像里。- 在设备
B中: 执行ll /data/maxhou/data2mount/test.txt。系统返回No such file or directory。结论: 虽然大家都在访问
/data/maxhou/data2mount/,但设备A访问的是镜像挂载后的内容 ,而设备B访问的是底层文件系统的空目录。
为什么容器需要Mount隔离?通过
MountNamespace,容器可以拥有自己独立的/目录(根文件系统)。容器启动时:
- 开启
Mount Namespace。- 使用
pivot_root或chroot将私有挂载点切换为根目录。- 这样,容器里的进程就只能看到镜像里的
/bin,/etc,而完全感知不到宿主机的存在。
4. 思维导图
