Linux Namespace机制
假设我们有了一个Docker项目,我们创建一个容器。
$ docker run -it ubuntu /bin/bash
-it 参数告诉了 Docker 项目在启动容器后,需要给我们分配一个文本输入 / 输出环境,也就是 TTY,跟容器的标准输入相关联,这样我们就可以和这个 Docker 容器进行交互了。而 /bin/bash 就是我们要在 Docker 容器里运行的程序。
所以上面这条指令的意思就是:
请帮我启动一个容器,在容器里执行 /bin/sh,并且给我分配一个命令行终端跟这个容器交互。
我们在容器中输入ps指令:
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh
2 root 0:00 ps
在这里可以看到,我们在 Docker 里最开始执行的 /bin/sh,就是这个容器内部的第 1 号进程(PID=1),而这个容器里一共只有两个进程在运行。这就意味着,前面执行的 /bin/sh,以及我们刚刚执行的 ps,已经被 Docker 隔离在了一个跟宿主机完全不同的世界当中。
我们在宿主机上运行/bin/bash程序时,操作系统会给它分配一个进程编号pid。这个进程编号就是进程的唯一标识,我们在docker中运行/bin/bash时,给它施展了一个“障眼法”,让它看不到其他的进程,这样它就会自己认为自己的pid=1。
这种机制,其实就是对被隔离应用的进程空间做了手脚,使得这些进程只能看到重新计算过的进程编号,这就是Linux里面的Namespace机制。
Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。
目前,Linux内核里面实现了7种不同类型的namespace。
名称 宏定义 隔离内容
Cgroup CLONE_NEWCGROUP Cgroup root directory (since Linux 4.6)
IPC CLONE_NEWIPC System V IPC, POSIX message queues (since Linux 2.6.19)
Network CLONE_NEWNET Network devices, stacks, ports, etc. (since Linux 2.6.24)
Mount CLONE_NEWNS Mount points (since Linux 2.4.19)
PID CLONE_NEWPID Process IDs (since Linux 2.6.24)
User CLONE_NEWUSER User and group IDs (started in Linux 2.6.23 and completed in Linux 3.8)
UTS CLONE_NEWUTS Hostname and NIS domain name (since Linux 2.6.19)
PID Namespace
在 Linux 系统中创建进程的系统调用是 clone()
int pid = clone(main_function, stack_size, SIGCHLD, NULL);
这个系统调用就会为我们创建一个新的进程,并且返回它的进程号 pid。
我们用 clone() 系统调用创建一个新进程时,就可以在参数中指定 CLONE_NEWPID 参数,比如:
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
这时,新创建的这个进程将会“看到”一个全新的进程空间,在这个进程空间里,它的 PID 是 1。
评论已关闭