第1天:Linux namespace概述
2019-06-18T09:24:19    1259    0    0
#### 从本文开始,我们将会从零开始带领大家学习Linux namespace的相关内容。 #### 在本文中,我们将会首先介绍namespace的基本概念。 ## 什么是namespace? Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。 Linux内核支持的namespaces如下: 名称 | 宏定义 | 隔离内容 --|--|-- 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) Ps:其中,cgroup namespace在4.6的内核中才实现,并且和cgroup v2关系密切,现在普及程度还不高,比如docker现在就还没有用它,所以在namespace系列文章中暂时不会介绍cgroup namespace。 ## 查看进程所属的namespaces 系统中的每个进程都有/proc/[pid]/ns/这样一个目录,里面包含了这个进程所属namespace的信息,里面每个文件的描述符都可以用来作为setns函数(后文会介绍)的参数。 查看当前bash进程所属的namespace信息: ![查看当前bash进程所属的namespace信息](/static/files/591/5989cee6e519f50ef7000031/33/images/2ec649230f7b0d7f02fde0c6df5da7ee.png) 其中: 1. 以ipc:[4026531839]为例,ipc是namespace的类型,4026531839是inode number,如果两个进程的ipc namespace的inode number一样,说明他们属于同一个namespace。这条规则对其他类型的namespace也同样适用。 2. 从上面的输出可以看出,对于每种类型的namespace,进程都会与一个对应的namespace ID关联。 ## namespace相关的API 和namespace相关的函数只有三个,如下所示: 一、`clone`: 创建一个新的进程并把他放到新的namespace中。 ``` int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg); ``` 其中:flags用于指定一个或者多个上面的CLONE_NEW*宏定义(当然也可以包含跟namespace无关的flags,多个flags用|进行分隔),这样就会创建一个或多个新的不同类型的namespace,并把新创建的子进程加入新创建的这些namespace中。 二、`setns`: 将当前进程加入到已有的namespace中。 ``` int setns(int fd, int nstype); ``` 其中: 1. fd:指向/proc/[pid]/ns/目录里相应namespace对应的文件,表示要加入哪个namespace 2. nstype:指定namespace的类型(上面的任意一个CLONE_NEW*),具体分为两种情况:1. 如果当前进程不能根据fd得到它的类型,如fd由其他进程创建,并通过UNIX domain socket传给当前进程,那么就需要通过nstype来指定fd指向的namespace的类型。2. 如果进程能根据fd得到namespace类型,比如这个fd是由当前进程打开的,那么nstype设置为0即可。 三、`unshare`: 使当前进程退出指定类型的namespace,并加入到新创建的namespace(相当于创建并加入新的namespace)。 ``` int unshare(int flags); ``` 其中:flags用于指定一个或者多个上面的CLONE_NEW*宏定义(当然也可以包含跟namespace无关的flags,多个flags用|进行分隔),这样就会创建一个或多个新的不同类型的namespace,并把新创建的子进程加入新创建的这些namespace中。 ### clone和unshare的区别 clone和unshare的功能都是创建并加入新的namespace, 他们的区别是: 1. unshare是使当前进程加入新的namespace。 2. clone是创建一个新的子进程,然后让子进程加入新的namespace,而当前进程保持不变。 ## 补充信息 当一个namespace中的所有进程都退出时,该namespace将会被销毁。当然还有其他方法让namespace一直存在,假设我们有一个进程号为1000的进程,以ipc namespace为例: 1. 通过`mount --bind`命令。例如: ``` mount --bind /proc/1000/ns/ipc /other/file ``` 此时,就算属于这个ipc namespace的所有进程都退出了,只要`/other/file`还在,这个ipc namespace就一直存在,其他进程就可以利用`/other/file`,通过`setns`函数加入到这个namespace。 2. 在其他namespace的进程中打开`/proc/1000/ns/ipc`文件,并一直持有这个文件描述符不关闭,以后就可以用`setns`函数加入这个namespace。

上一篇:

下一篇: 第2天:UTS namespace详解

0条评论