本文来源于我的个人博客
www.chenbiaolong.com
欢迎访问
概要
传统上,linux很多资源是全局管理的,例如系统中所有的进程是通过pid标识的,这意味着内核管理着一个全局pid表,进程号必须为唯一的。类似的还有内核的文件系统挂载点数据信息、用户ID号等。我们知道,要实现虚拟化必须要有独立的资源分配,才能使容器之间不互相影响,那如何使这些全局表局域化呢?答案是namespace。Namespace将传统的全局资源变为某个名字空间的局域资源。目前linux内核实现的namespace主要有:
1.Mount namespace(CLONE_NEWNS):系统挂载点
2.UTS namespace (CLONE_NEWUTS):Hostname等信息
3.IPC namespace(CLONE_NEWIPC):进程间通讯
4.PID namespace(CLONE_NEWPID):进程号
5.Network namespace(CLONE_NEWNET):网络相关资源
6.User namespace(CLONE_NEWUSER):用户ID
可以看出,以上的这些系统资源在没有引入namespace时是由内核全局管理的。linux内核为了支持容器虚拟化功能,加入了以上6种namespace,实现这些全局系统资源局域化,使每一个namespace空间都拥有独立的一套系统资源。由于本文主要讲述docker虚拟化的实现原理,考虑到篇幅,将主要从内核角度简介linux的PID namespace。PID namespace使属于不同的名字空间的进程可以拥有相同的进程号,对实现docker的虚拟化至关重要。
namespace内核相关结构
在task_struct 结构中有一个结构体指针nsproxy。nsproxy结构体定义了内核支持的namespace。
struct task_struct {
...
/* namespaces */
struct nsproxy *nsproxy;
...
}
nsproxy的定义如下(Linux/include/linux/nsproxy.h):
struct nsproxy {
atomic_t count;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
struct pid_na