linux中的namespace

     本文将就namespace这个知识点,进行简单的归纳总结,力求通俗易通。在资料汇总的过程中,参考了许多网上的博客资料,在文章尾部给出相关链接。

     namespace,命名空间,从名字上看,应该是类似于包含许多名字的空间,打个比方,三年一班的小明和三年二班的小明,虽说他们名字是一样的,但是所在班级不一样,那么,在全年级排行榜上面,即使出现两个名字一样的小明,也会通过各自的学号来区分。对于学校来说,每个班级就相当于是一个命名空间,这个空间的名称是班级号。班级号用于描述逻辑上的学生分组信息,至于什么学生分配到1班,什么学生分配到2班,那就由学校层面来统一调度。大致应该就是这么个意思,恩。

C++中的命名空间

     命名空间这个概念不仅仅在kernel中有使用,在其他语言中也有所体现。例如在C++中,标准C++库中所包含的所有内容(包括常量、变量、结构、类和函数)都被定义在命名空间std中。我们可以定义有名命名空间,也可以定义无名命名空间,命名空间可以嵌套定义,

   1:  有名的命名空间:
   2:   
   3:         namespace 命名空间名 {
   4:   
   5:                声明序列可选
   6:   
   7:         }
   8:   
   9:  无名的命名空间:
  10:   
  11:         namespace {
  12:   
  13:                声明序列可选
  14:   
  15:         }
  16:   

    在C++中,如果代码的最前面没有使用 using namespace std 的话,对于输入输出流,就必须指定所在的命名空间(std::cout <<),否则编译器会找不到他们的具体实现。可以这么说,命名空间是对全局作用域的细分。

Linux中的namespace

    在Linux系统中,可以同时存在多用户多进程,那么对他们的运行协调管理,通过进程调度和进度管理可以解决,但是,整体资源是有限的,怎么把有限的资源(进程号、通信资源、网络资源等等)合理分配给各个用户所在的进程?Linux中提出了namespace机制,这是一种轻量级的虚拟化形式。再次之前,Linux中很多资源是全局管理的,例如,系统中所有进程,都是通过PID来标识的,就像每个学生的学号一样,在整个学校范围内,肯定是唯一标识这个学生的。用户的ID管理,各个用户通过全局为UID来标识,每个学校的校长也只有有一个,它的UID为0,权利最大,可以对学校内全部老师和学生发起命令。每个学生可以看到其他学生的活动,但是无权把他们赶出学校,这是可以理解的。这种集中统一的管理方式,很适合大规模人群的管理。

    随着大数据、虚拟化的兴起,Linux为了提供更加精细的资源分配管理机制,给出了namespace机制解决方法。

技术分享

命名空间建立系统的不同视图, 对于每一个命名空间,从用户看起来,应该像一台单独的Linux计算机一样,有自己的init进程(PID为0),其他进程的PID依次递增,A和B空间都有PID为0的init进程,子容器的进程映射到父容器的进程上,父容器可以知道每一个子容器的运行状态,而子容器与子容器之间是隔离的。

    Linux中有chroot的系统调用,该方法将进程限制到文件系统的某一部分,是一种简单的命名空间机制。

    在task_struct结构体中,有struct nsproxy *nsproxy 这个成员变量,

   1:  /*
   2:   * A structure to contain pointers to all per-process
   3:   * namespaces - fs (mount), uts, network, sysvipc, etc.
   4:   *
   5:   * ‘count‘ is the number of tasks holding a reference.
   6:   * The count for each namespace, then, will be the number
   7:   * of nsproxies pointing to it, not the number of tasks.
   8:   *
   9:   * The nsproxy is shared by tasks which share all namespaces.
  10:   * As soon as a single namespace is cloned or unshared, the
  11:   * nsproxy is copied.
  12:   */
  13:  struct nsproxy {
  14:      atomic_t count;
  15:      spinlock_t nslock;
  16:      struct uts_namespace *uts_ns;
  17:      struct ipc_namespace *ipc_ns;
  18:      struct mnt_namespace *mnt_ns;
  19:      struct pid_namespace *pid_ns;
  20:  };

uts_ns:UTS为Unix Timesharing System的简称,包含内存名称、版本、底层体系结构等信息。

ipc_ns:保存所有与进程间通讯(IPC)有关的信息。

mnt_ns: 当前装载的文件系统

pid_ns: 有关进程ID的信息

在高级版本上,还有net_ns的网络信息,user_ns的资源配额的信息等。

下面以uts命名空间为例子,介绍如何创建用户空间。

从上面的框架图可以看出,所谓的子空间,就是父进程fork一个子进程出来,然后子进程与父进程不共享某些资源,那么,就可以说,这个子进程在它自己的那个命名空间内。

要达到这种效果,就必须对fork的行为进行精确控制,内核提供的如下参数来设置:

技术分享

UTS命名空间没有层次结构,所有信息都汇集到如下结构:

技术分享 ,kref是引用计数器,用于跟踪内核中有多少地方使用uts_namespace的实例。它提供的属性信息如下:

技术分享 ,从名字上,可以得知uts包含系统名称、版本号、机器名称等等。使用uname -a可以查看这些信息。

系统初始默认值保持在init/version.c 中的init_uts_ns全局变量中,在系统初始化task时,配置init_task。

用户可以在fork时,传入CLONE_NEWUTS标准,创建新的UTS命名空间。执行此操作,会生成先前uts_namespace的一份副本,当前进程内部的nsproxy指向此副本,然后就可以修改了。父子进程对nx_prosy的修改不会相互影响。

    由于最初的父命名空间需要掌握所有子命名空间的所有pid信息,所有,在各级层次的命名空间的fork中,pid的分配是需要统一协调控制,对于各级子命名空间中的task_struct来说,同一个pid在不同命名空间看到的是不一样的。 

   同一个进程可以属于多个namespace,多个进程可以使用同一个namespace,

参考链接:

C++中的namespace

PID namespace浅分析

PID namespcae浅分析 续

Linux内核的namespace机制分析

Technorati 标签:

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。