Namespaces命名空间
wikepedia定义:In general, a namespace is a container for a set of identifiers (also known as symbols, names).[1][2] Namespaces provide a level of direction tospecific identifiers, thus making it possible to distinguish between identifierswith the same exact name. For example, a surname could be thought ofas a namespace that makes it possible to distinguish people who have the samegiven name. In computerprogramming, namespaces are typically employed for the purpose ofgrouping symbols and identifiers around a particular functionality.
一、c++中的namespace
在C++语言中,命名空间使用namespace来声明,并使用{ }来界定命名空间的作用域。命名空间可以是全局的,也可以位于另一命名空间之中;但不能在类和代码块之中。按照是否有名字,可分为有名字的命名空间与无名命名空间。可以多次声明和定义同一命名空间,每次给这一命名空间添加新成员。编译器自动合并这些同名的命名空间。
简单示例:
二、linux中的namespaces机制:
Linux Namespace是Linux提供的一种OS-level virtualization的方法。目前在Linux系统上实现OS-level virtualization的系统有Linux VServer、OpenVZ、LXC Linux Container、Virtuozzo等,其中Virtuozzo是OpenVZ的商业版本。以上种种本质来说都是使用了Linux Namespace来进行隔离。
每个进程的命名空间都抽象成一个nsproxy指针,共享同一个命名空间的进程指向同一个指针,指针的结构通过引用计数(count)来确定使用者数目。目前Linux系统实现的命名空间子系有UTS、IPC、MNT、PID以及NET网络子模块。
在Linux/include/linux/sched.h中struct task_struct中找到对应的namespace结构:
struct task_struct {
...
struct nsproxy *nsproxy;
...
};
// nsproxy是每个进程自己的namespace结构
Linux/include/linux/nsproxy.h中找到具体的namespace结构:
struct nsproxy {
atomic_t count;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
struct pid_namespace *pid_ns;
struct net *net_ns;
};
extern struct nsproxy init_nsproxy;
Linux系统命名空间的UTS、IPC、MNT、PID以及NET网络子模块相关定义分别在一下文件中:在Linux/include/linux/utsname.h、Linux/include/linux/ipc_namespace.h、Linux/include/linux/mnt_namespace.h、Linux/include/linux/pid_namespace.h、Linux/include/net/net_namespace.h。
三、下面简单分析linux中PID命名空间(namespace)
linux通过命名空间管理进程pid,对于同一进程(同一个task_struct),在不同的命名空间中,看到的pid号不相同,每个pid命名空间有一套自己的pid管理方法,所以在不同的命名空间中调用getpid(),看到的pid号是不同的。
PID是命名空间中较为复杂的模块,因为PID命名空间是有层次的,在高层次命名空间能看到低命名空间信息,反之不行。
pid namespace原理:
PID层次化命名空间结构图:
注解:进程在不同命名空间有不同的数据表示,获取一个进程信息进程号和空间信息才能唯一确定一个进程。
在Linux/include/linux/pid_namespace.h:
注释:
child_reaper指向的进程相当于全局命名空间的init进程,其中一个重要目的是对孤儿进程进行回收;
level记录该pid namespace的深度;
*parent记录父pid namespace。
注释:
nr表示命名空间中的标示;
*ns表示命名空间;
即在*ns命名空间的pid是nr;
pid_chain系统所有的upid通过pid_chain挂在同一个全局链表里;
count表示应用次数;
level表示这个pid深度;
tasks表示一个pid可能对应多个task_struct;
numbers表示一个task_struct在每一个namespace的id,number[0]表示最顶层的namespace,level = 0,number[1]表示level =1。
PID命名空间在进程中的整体位置:
简单示例:
示例结果:
注:关于linux的namespace机制只了解皮毛,还有很多东西需要继续学习。