Docker底层-IPC Namespace(进程间通信隔离)

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 隔离!                    │
└─────────────────────────────────────────────────────────┘
相关推荐
一只旭宝2 小时前
Linux专题十三:shell脚本编程
linux·运维·服务器
浅陌sss2 小时前
使用Unity从IIS搭建的文件服务器下载资源时出现HTTP/1.1 404 Not Found
运维·服务器·http
电商API&Tina3 小时前
【电商API接口】多电商平台数据API接入方案(附带实例)
运维·开发语言·数据库·chrome·爬虫·python·jenkins
eddy-原3 小时前
ELKStack 与 Kubernetes 核心基础知识点综合作业
云原生·容器·kubernetes
V胡桃夹子3 小时前
Docker快速部署apollo
运维·docker·容器
有谁看见我的剑了?3 小时前
ssh服务限制用户登录
运维·服务器·ssh
航Hang*3 小时前
第三章:网络系统建设与运维(中级)——交换技术
运维·笔记·计算机网络·华为·ensp·交换机
终端行者3 小时前
Nginx端到端反向代理https配置
运维·nginx·https
代码炼金术士3 小时前
认识JVM
运维·服务器·jvm