IPC Namespace 详解
1. IPC Namespace 的作用
IPC = Inter-Process Communication(进程间通信)
作用:隔离进程间通信资源,让不同 Namespace 中的进程无法互相通信。
┌─────────────────────────────────────────────────────────┐
│ Linux 主机 │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ IPC NS 1 │ │ IPC NS 2 │ │
│ │ │ │ │ │
│ │ 共享内存 1 │ │ 共享内存 2 │ │
│ │ 消息队列 1 │ │ 消息队列 2 │ │
│ │ 信号量 1 │ │ 信号量 2 │ │
│ │ │ │ │ │
│ │ 完全隔离 │ │ 完全隔离 │ │
│ └──────────────┘ └──────────────┘ │
│ │
│ 不同 Namespace 的进程无法互相通信! │
└─────────────────────────────────────────────────────────┘
2. IPC Namespace 隔离的资源
IPC Namespace 隔离三种进程间通信机制:
1. System V IPC
- 共享内存(Shared Memory)
- 消息队列(Message Queue)
- 信号量(Semaphore)
2. POSIX IPC
- POSIX 消息队列
- POSIX 信号量
- POSIX 共享内存
3. 实际用例演示
用例 1:创建共享内存(System V IPC)
# 步骤 1:创建新的 IPC Namespace
sudo unshare --ipc /bin/bash
# 步骤 2:在 Namespace 中创建共享内存
ipcmk -M 1024
# 输出:shmid: 0
# 步骤 3:查看共享内存
ipcs -m
# 输出:
# ------ Shared Memory Segments --------
# key shmid owner perms bytes nattch status
# 0x00000000 0 root 644 1024 0
# 步骤 4:退出 Namespace
exit
# 步骤 5:在主机上查看
ipcs -m
# 输出:(看不到 Namespace 中创建的共享内存)
4. 详细演示:共享内存隔离
演示 1:在 Namespace 中创建共享内存

演示 2:多个 IPC Namespace 同时存在
# 终端 1:IPC Namespace 1
sudo unshare --ipc bash
ipcmk -M 1024
ipcs -m
# 输出:shmid: 0
# 终端 2:IPC Namespace 2
sudo unshare --ipc bash
ipcmk -M 2048
ipcs -m
# 输出:shmid: 0(注意:也是 0,因为每个 Namespace 独立编号)
# 终端 3:主机
ipcs -m
# 输出:(看不到两个 Namespace 中的共享内存)
┌─────────────────────────────────────────────────────────┐
│ IPC Namespace 1 │
│ │
│ 共享内存: │
│ shmid: 0 (1024 bytes) │
│ │
│ 只能看到自己的共享内存 │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ IPC Namespace 2 │
│ │
│ 共享内存: │
│ shmid: 0 (2048 bytes) │
│ │
│ 只能看到自己的共享内存 │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ 主机 IPC Namespace │
│ │
│ 共享内存: │
│ (看不到 Namespace 1 和 2 的) │
└─────────────────────────────────────────────────────────┘
验证命令总结
# 1. 创建 IPC Namespace
sudo unshare --ipc /bin/bash
# 2. 创建共享内存
ipcmk -M <大小>
# 3. 创建消息队列
ipcmk -Q n
# 4. 创建信号量
ipcmk -S
# 5. 查看所有 IPC 资源
ipcs -a
# 6. 查看共享内存
ipcs -m
# 7. 查看消息队列
ipcs -q
# 8. 查看信号量
ipcs -s
# 9. 删除共享内存
ipcrm -m <shmid>
# 10. 删除消息队列
ipcrm -q <msqid>
# 11. 删除信号量
ipcrm -s <semid>
# 12. 查看 IPC Namespace
readlink /proc/self/ns/ipc


root@LAPTOP-LU4HDAFV:~# sudo unshare --ipc /bin/bash
root@LAPTOP-LU4HDAFV:~# ipcmk -M 2048
Shared memory id: 0
root@LAPTOP-LU4HDAFV:~# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x6b97cbc6 0 root 644 2048 0
root@LAPTOP-LU4HDAFV:~# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x6b97cbc6 0 root 644 2048 0
root@LAPTOP-LU4HDAFV:~# exit
exit
root@LAPTOP-LU4HDAFV:~# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
root@LAPTOP-LU4HDAFV:~# sudo unshare --ipc /bin/bash
root@LAPTOP-LU4HDAFV:~# ipcmk -M 1024
Shared memory id: 0
root@LAPTOP-LU4HDAFV:~# ipcmk -Q
Message queue id: 0
root@LAPTOP-LU4HDAFV:~# ipcmk -S
ipcmk: option requires an argument -- 'S'
Try 'ipcmk --help' for more information.
root@LAPTOP-LU4HDAFV:~# ipcmk -S 1
Semaphore id: 0
root@LAPTOP-LU4HDAFV:~# ipcmk -a
ipcmk: invalid option -- 'a'
Try 'ipcmk --help' for more information.
root@LAPTOP-LU4HDAFV:~# ipcs -a
------ Message Queues --------
key msqid owner perms used-bytes messages
0xf59890ae 0 root 644 0 0
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0xa4e2c6d0 0 root 644 1024 0
------ Semaphore Arrays --------
key semid owner perms nsems
0x0d4e54b8 0 root 644 1
root@LAPTOP-LU4HDAFV:~#
总结
| 机制 | 用途 | 类比 | 命令 |
|---|---|---|---|
| 共享内存 | 多个进程共享同一块内存 | 共享黑板 | ipcmk -M |
| 消息队列 | 进程间发送和接收消息 | 邮箱系统 | ipcmk -Q |
| 信号量 | 控制同时访问资源的进程数 | 停车场车位 | ipcmk -S |
这三种机制都被 IPC Namespace 隔离,不同 Namespace 的进程无法互相访问对方的 IPC 资源。
IPC Namespace 隔离的资源详解
2. IPC Namespace 隔离的资源(图示)
IPC Namespace 隔离三种进程间通信机制:
1. System V IPC
┌─────────────────────────────────────────────────────────┐
│ System V IPC(三种机制) │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 1. 共享内存(Shared Memory) │ │
│ │ │ │
│ │ 进程 A 进程 B │ │
│ │ │ │ │ │
│ │ └──────┐ ┌─────┘ │ │
│ │ │ │ │ │
│ │ ┌────▼──────▼────┐ │ │
│ │ │ 共享内存区域 │ │ │
│ │ │ (Shared Memory)│ │ │
│ │ └─────────────────┘ │ │
│ │ │ │
│ │ 多个进程可以同时访问同一块内存 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 2. 消息队列(Message Queue) │ │
│ │ │ │
│ │ 进程 A ──发送消息──> [消息队列] ──接收消息──> 进程 B│
│ │ │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ 消息队列 │ │ │
│ │ │ ┌────┐ ┌────┐ ┌────┐│ │ │
│ │ │ │消息1│ │消息2│ │消息3││ │ │
│ │ │ └────┘ └────┘ └────┘│ │ │
│ │ └──────────────────────┘ │ │
│ │ │ │
│ │ 进程通过消息队列发送和接收消息 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 3. 信号量(Semaphore) │ │
│ │ │ │
│ │ 进程 A 进程 B │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ │ └──────┐ ┌─────┘ │ │
│ │ │ │ │ │
│ │ ┌────▼──────▼────┐ │ │
│ │ │ 信号量 │ │ │
│ │ │ (计数器) │ │ │
│ │ │ 值: 3 │ │ │
│ │ └─────────────────┘ │ │
│ │ │ │
│ │ 用于进程同步和互斥访问资源 │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
详细图示:IPC Namespace 隔离效果
场景:两个 IPC Namespace 的隔离
┌─────────────────────────────────────────────────────────┐
│ Linux 主机 │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ IPC Namespace 1 │ │
│ │ │ │
│ │ 进程 A 进程 B │ │
│ │ │ │ │ │
│ │ └──────┐ ┌─────┘ │ │
│ │ │ │ │ │
│ │ ┌────▼──────▼────┐ │ │
│ │ │ 共享内存 1 │ │ │
│ │ │ shmid: 0 │ │ │
│ │ └─────────────────┘ │ │
│ │ │ │
│ │ 进程 C ──消息──> [消息队列 1] ──消息──> 进程 D │ │
│ │ msqid: 0 │ │
│ │ │ │
│ │ 进程 E ──等待──> [信号量 1] <──等待── 进程 F │ │
│ │ semid: 0 │ │
│ │ │ │
│ │ 只能看到自己的 IPC 资源! │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ IPC Namespace 2 │ │
│ │ │ │
│ │ 进程 G 进程 H │ │
│ │ │ │ │ │
│ │ └──────┐ ┌─────┘ │ │
│ │ │ │ │ │
│ │ ┌────▼──────▼────┐ │ │
│ │ │ 共享内存 2 │ │ │
│ │ │ shmid: 0 │ ← 注意:也是 0! │ │
│ │ └─────────────────┘ │ │
│ │ │ │
│ │ 进程 I ──消息──> [消息队列 2] ──消息──> 进程 J │ │
│ │ msqid: 0 │ │
│ │ │ │
│ │ 进程 K ──等待──> [信号量 2] <──等待── 进程 L │ │
│ │ semid: 0 │ │
│ │ │ │
│ │ 只能看到自己的 IPC 资源! │ │
│ │ 看不到 Namespace 1 的资源! │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ 完全隔离:两个 Namespace 的进程无法互相访问 IPC 资源! │
└─────────────────────────────────────────────────────────┘
详细图示:共享内存(Shared Memory)
┌─────────────────────────────────────────────────────────┐
│ IPC Namespace 1 - 共享内存示例 │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 进程 A (PID: 1001) │ │
│ │ │ │
│ │ 写入数据到共享内存: │ │
│ │ shm_write(shmid: 0, "Hello") │ │
│ │ │ │ │
│ │ └─────────┐ │ │
│ └───────────────────┼──────────────────────────┘ │
│ │ │
│ │ │
│ ┌───────────────────┼──────────────────────────┐ │
│ │ 进程 B (PID: 1002) │ │ │
│ │ │ │ │
│ │ 从共享内存读取: │ │ │
│ │ shm_read(shmid: 0) │ │
│ │ │ │ │
│ │ └─────────┐ │ │
│ └───────────────────┼──────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 共享内存 (shmid: 0) │ │
│ │ │ │
│ │ ┌────────────────────────────────────┐ │ │
│ │ │ 地址: 0x7f8a5c000000 │ │ │
│ │ │ 大小: 1024 bytes │ │ │
│ │ │ 内容: "Hello" │ │ │
│ │ └────────────────────────────────────┘ │ │
│ │ │ │
│ │ 进程 A 和 B 共享这块内存 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ 在 IPC Namespace 2 中: │
│ ┌──────────────────────────────────────────────┐ │
│ │ 进程 C 尝试访问 shmid: 0 │ │
│ │ │ │
│ │ 结果:失败! │ │
│ │ 错误:No such file or directory │ │
│ │ │ │
│ │ 因为 Namespace 2 中的 shmid: 0 │ │
│ │ 是另一个共享内存! │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
详细图示:消息队列(Message Queue)
┌─────────────────────────────────────────────────────────┐
│ IPC Namespace 1 - 消息队列示例 │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 进程 A (发送者) │ │
│ │ │ │
│ │ msgsnd(msqid: 0, "Message 1") │ │
│ │ │ │ │
│ │ └─────────┐ │ │
│ └───────────────────┼──────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 消息队列 (msqid: 0) │ │
│ │ │ │
│ │ ┌────────────────────────────────────┐ │ │
│ │ │ 队列头部 │ │ │
│ │ │ ┌──────────┐ │ │ │
│ │ │ │消息 1 │ ← 进程 A 发送 │ │ │
│ │ │ └──────────┘ │ │ │
│ │ │ ┌──────────┐ │ │ │
│ │ │ │消息 2 │ │ │ │
│ │ │ └──────────┘ │ │ │
│ │ │ ┌──────────┐ │ │ │
│ │ │ │消息 3 │ │ │ │
│ │ │ └──────────┘ │ │ │
│ │ │ 队列尾部 │ │ │
│ │ └────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 进程 B (接收者) │ │
│ │ │ │
│ │ msgrcv(msqid: 0) │ │
│ │ │ │ │
│ │ └─────────┐ │ │
│ │ 收到:"Message 1" │ │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ 在 IPC Namespace 2 中: │
│ ┌──────────────────────────────────────────────┐ │
│ │ 进程 C 尝试访问 msqid: 0 │ │
│ │ │ │
│ │ 结果:失败! │ │
│ │ 错误:No such file or directory │ │
│ │ │ │
│ │ 因为 Namespace 2 有自己的消息队列! │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
详细图示:信号量(Semaphore)
┌─────────────────────────────────────────────────────────┐
│ IPC Namespace 1 - 信号量示例 │
│ │
│ 场景:多个进程竞争访问共享资源 │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 进程 A │ │
│ │ │ │
│ │ sem_wait(semid: 0) ← 等待信号量 │ │
│ │ │ │ │
│ │ └─────────┐ │ │
│ └───────────────────┼──────────────────────────┘ │
│ │ │
│ ┌───────────────────┼──────────────────────────┐ │
│ │ 进程 B │ │ │
│ │ │ │ │
│ │ sem_wait(semid: 0) │ │
│ │ │ │ │
│ │ └─────────┐ │ │
│ └───────────────────┼──────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 信号量 (semid: 0) │ │
│ │ │ │
│ │ ┌────────────────────────────────────┐ │ │
│ │ │ 计数器值: 3 │ │ │
│ │ │ │ │ │
│ │ │ 进程 A: sem_wait() │ │ │
│ │ │ ↓ │ │ │
│ │ │ 计数器: 3 → 2 │ │ │
│ │ │ │ │ │
│ │ │ 进程 B: sem_wait() │ │ │
│ │ │ ↓ │ │ │
│ │ │ 计数器: 2 → 1 │ │ │
│ │ │ │ │ │
│ │ │ 进程 C: sem_wait() │ │ │
│ │ │ ↓ │ │ │
│ │ │ 计数器: 1 → 0 │ │ │
│ │ │ │ │ │
│ │ │ 进程 D: sem_wait() │ │ │
│ │ │ ↓ │ │ │
│ │ │ 计数器: 0 → 阻塞等待 │ │ │
│ │ └────────────────────────────────────┘ │ │
│ │ │ │
│ │ 用于控制同时访问资源的进程数量 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ 在 IPC Namespace 2 中: │
│ ┌──────────────────────────────────────────────┐ │
│ │ 进程 E 尝试访问 semid: 0 │ │
│ │ │ │
│ │ 结果:失败! │ │
│ │ 错误:No such file or directory │ │
│ │ │ │
│ │ 因为 Namespace 2 有自己的信号量! │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
整对比图:隔离效果
┌─────────────────────────────────────────────────────────┐
│ 主机 IPC Namespace │
│ │
│ ipcs -a │
│ ┌──────────────────────────────────────────────┐ │
│ │ (可能有一些主机的 IPC 资源) │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
│ 创建 IPC Namespace
│
┌───────────┴───────────┐
│ │
↓ ↓
┌───────────────────┐ ┌───────────────────┐
│ IPC Namespace 1 │ │ IPC Namespace 2 │
│ │ │ │
│ ipcs -a │ │ ipcs -a │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ 共享内存 1 │ │ │ │ 共享内存 2 │ │
│ │ shmid: 0 │ │ │ │ shmid: 0 │ │
│ └───────────────┘ │ │ └───────────────┘ │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ 消息队列 1 │ │ │ │ 消息队列 2 │ │
│ │ msqid: 0 │ │ │ │ msqid: 0 │ │
│ └───────────────┘ │ │ └───────────────┘ │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ 信号量 1 │ │ │ │ 信号量 2 │ │
│ │ semid: 0 │ │ │ │ semid: 0 │ │
│ └───────────────┘ │ │ └───────────────┘ │
│ │ │ │
│ 看不到 Namespace 2│ │ 看不到 Namespace 1│
│ 的资源! │ │ 的资源! │
└───────────────────┘ └───────────────────┘
总结图:三种 IPC 机制
┌─────────────────────────────────────────────────────────┐
│ System V IPC 三种机制 │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 1. 共享内存 │ │ 2. 消息队列 │ │ 3. 信号量 │ │
│ │ │ │ │ │ │ │
│ │ 多个进程 │ │ 进程间发送 │ │ 进程同步 │ │
│ │ 共享同一块 │ │ 和接收消息 │ │ 和互斥访问 │ │
│ │ 内存区域 │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ 命令: │ │ 命令: │ │ 命令: │ │
│ │ ipcmk -M │ │ ipcmk -Q │ │ ipcmk -S │ │
│ │ ipcs -m │ │ ipcs -q │ │ ipcs -s │ │
│ │ ipcrm -m │ │ ipcrm -q │ │ ipcrm -s │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ 所有这些资源都被 IPC Namespace 隔离! │
└─────────────────────────────────────────────────────────┘