Linux命名空间【IPC】
Linux命名空间【IPC】
什么是 IPC Namespace?
IPC Namespace是Linux内核中的一种命名空间,用于隔离进程间通信资源。它主要隔离以下两类IPC机制:
- System V IPC:消息队列(
msgget)、信号量(semget)、共享内存(shmget) - POSIX 消息队列
通过 IPC Namespace,不同命名空间中的进程拥有各自独立的 IPC 资源,相互隔离,互不干扰。
IPC Namespace 的作用
- 实现容器(如 Docker)中进程间通信的隔离,防止容器之间的 IPC 资源冲突
- 多租户环境中保护资源,提升安全性
- 支持多个进程组独立管理和清理自己的 IPC 资源
IPC Namespace 的创建与使用
创建 IPC Namespace 通常通过 Linux 系统调用 clone() 或 unshare(),在创建新进程或切换命名空间时指定 CLONE_NEWIPC 标志。
IPC Namespace 示例代码(C 语言)
下面的代码演示:
- 创建一个新进程,进入新的 IPC Namespace
- 在新的 IPC Namespace 中创建一个 System V 消息队列
- 父进程依然在原始 IPC Namespace 中,不能访问子进程的消息队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
c
复制编辑
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#define STACK_SIZE (1024 * 1024) // 1MB
struct msgbuf {
long mtype;
char mtext[100];
};
// 子进程函数:运行在新的 IPC Namespace
int child_func(void *arg) {
printf("子进程 PID: %d,进入新的 IPC Namespace\n", getpid());
// 创建消息队列
int msgid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
if (msgid == -1) {
perror("msgget");
return -1;
}
printf("子进程创建消息队列 ID: %d\n", msgid);
// 发送一条消息
struct msgbuf msg = {1, "Hello from child IPC namespace!"};
if (msgsnd(msgid, &msg, strlen(msg.mtext) + 1, 0) == -1) {
perror("msgsnd");
return -1;
}
printf("子进程发送消息成功\n");
// 等待父进程结束
sleep(5);
// 删除消息队列
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
perror("msgctl IPC_RMID");
return -1;
}
printf("子进程删除消息队列\n");
return 0;
}
int main() {
char *stack = malloc(STACK_SIZE);
if (!stack) {
perror("malloc");
exit(EXIT_FAILURE);
}
char *stack_top = stack + STACK_SIZE;
// 创建子进程,使用 CLONE_NEWIPC 创建新的 IPC Namespace
pid_t child_pid = clone(child_func, stack_top, CLONE_NEWIPC | SIGCHLD, NULL);
if (child_pid == -1) {
perror("clone");
free(stack);
exit(EXIT_FAILURE);
}
printf("父进程 PID: %d,子进程 PID: %d\n", getpid(), child_pid);
// 父进程等待子进程结束
waitpid(child_pid, NULL, 0);
free(stack);
printf("父进程结束\n");
return 0;
}
编译运行说明
1
2
3
4
5
6
bash
复制编辑
gcc -o ipc_ns ipc_ns.c
sudo ./ipc_ns
需要
sudo权限,因为CLONE_NEWIPC需要特权。
程序执行效果说明
- 子进程会进入新的 IPC Namespace,创建一个消息队列,发送消息,并在退出前删除它。
- 父进程依然在原来的 IPC Namespace,无法访问或看到子进程新建的消息队列。
- 这验证了 IPC Namespace 的隔离效果。
总结
- IPC Namespace 让容器或进程组可以独立管理自己的 IPC 资源。
- 它是实现容器隔离的重要命名空间之一。
- 使用
clone或unshare携带CLONE_NEWIPC标志即可创建新的 IPC Namespace。
This post is licensed under CC BY 4.0 by the author.