首页 > 系统 > Linux > 正文

Linux的命名空间怎样理解

2024-08-27 23:55:06
字体:
来源:转载
供稿:网友
  小编今天带大家了解Linux的命名空间如何理解,文中知识点介绍的非常详细。觉得有帮助的朋友可以跟着小编一起浏览文章的内容,希望能够帮助更多想解决这个问题的朋友找到问题的答案,下面跟着小编一起深入学习“Linux的命名空间如何理解”的知识吧。
 
  一、基本概念
    命名空间(Linux namespace)是linux内核针对实现容器虚拟化映入的一个特性。我们创建的每个容器都有自己的命名空间,运行在其中的应用都像是在独立的操作系统中运行一样,命名空间保证了容器之间互不影响。
 
    Linux的命名空间机制提供了一种资源隔离的解决方案。PID,IPC,Network等系统资源不再是全局性的,而是属于特定的Namespace。Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。
 
    传统上,在Linux以及其他衍生的UNIX变体中,许多资源是全局管理的。例如,系统中的所有进程按照惯例是通过PID标识的,这意味着内核必须管理一个全局的PID列表。而且,所有调用者通过uname系统调用返回的系统相关信息(包括系统名称和有关内核的一些信息)都是相同的。用户ID的管理方式类似,即各个用户是通过一个全局唯一的UID号标识。
 
    全局ID使得内核可以有选择地允许或拒绝某些特权。虽然UID为0的root用户基本上允许做任何事,但其他用户ID则会受到限制。例如UID为n的用户,不允许杀死属于用户m的进程( m≠ n)。但这不能防止用户看到彼此,即用户n可以看到另一个用户m也在计算机上活动。只要用户只能操纵他们自己的进程,这就没什么问题,因为没有理由不允许用户看到其他用户的进程。
 
    但有些情况下,这种效果可能是不想要的。如果提供Web主机的供应商打算向用户提供Linux计算机的全部访问权限,包括root权限在内。传统上,这需要为每个用户准备一台计算机,代价太高。使用KVM或VMWare提供的虚拟化环境是一种解决问题的方法,但资源分配做得不是非常好。计算机的各个用户都需要一个独立的内核,以及一份完全安装好的配套的用户层应用。
 
    命名空间提供了一种不同的解决方案,所需资源较少。在虚拟化的系统中,一台物理计算机可以运行多个内核,可能是并行的多个不同的操作系统。而命名空间则只使用一个内核在一台物理计算机上运作,前述的所有全局资源都通过命名空间抽象起来。这使得可以将一组进程放置到容器中,各个容器彼此隔离。隔离可以使容器的成员与其他容器毫无关系。但也可以通过允许容器进行一定的共享,来降低容器之间的分隔。例如,容器可以设置为使用自身的PID集合,但仍然与其他容器共享部分文件系统。
 
  二、实现
    命名空间的实现需要两个部分:每个子系统的命名空间结构,将此前所有的全局组件包装到命名空间中;将给定进程关联到所属各个命名空间的机制。
 
    子系统此前的全局属性现在封装到命名空间中,每个进程关联到一个选定的命名空间。每个可以感知命名空间的内核子系统都必须提供一个数据结构,将所有通过命名空间形式提供的对象集中起来。 struct nsproxy用于汇集指向特定于子系统的命名空间包装器的指针。在文件nsproxy.h中有:
 
  /*
   * A structure to contain pointers to all per-process
   * namespaces - fs (mount), uts, network, sysvipc, etc.
   *
   * The pid namespace is an exception -- it's accessed using
   * task_active_pid_ns.  The pid namespace here is the
   * namespace that children will use.
   *
   * 'count' is the number of tasks holding a reference.
   * The count for each namespace, then, will be the number
   * of nsproxies pointing to it, not the number of tasks.
   *
   * The nsproxy is shared by tasks which share all namespaces.
   * As soon as a single namespace is cloned or unshared, the
   * nsproxy is copied.
   */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_for_children;
   struct net      *net_ns;
   struct time_namespace *time_ns;
   struct time_namespace *time_ns_for_children;
   struct cgroup_namespace *cgroup_ns;};
    当前内核的以下范围可以感知到命名空间
 
    1、 UTS命名空间包含了运行内核的名称、版本、底层体系结构类型等信息。 UTS是UNIXTimesharing System的简称。
 
    2、保存在struct ipc_namespace中的所有与进程间通信( IPC)有关的信息。
 
    3、 已经装载的文件系统的视图,在struct mnt_namespace中给出。
 
    4、 有关进程ID的信息,由struct pid_namespace提供。
 
    5、 struct user_namespace保存的用于限制每个用户资源使用的信息。
 
    6、struct net_ns包含所有网络相关的命名空间参数。
 
    当我讨论相应的子系统时,会介绍各个命名空间容器的内容。在由于在创建新进程时可使用fork建立一个新的命名空间,因此必须提供控制该行为的适当的标志。每个命名空间都有一个对应的标志,在sched.h文件内:
 
  #define CLONE_NEWCGROUP 0x02000000 /* New cgroup namespace */
  #define CLONE_NEWUTS 0x04000000 /* New utsname namespace */
  #define CLONE_NEWIPC 0x08000000 /* New ipc namespace */
  #define CLONE_NEWUSER 0x10000000 /* New user namespace */
  #define CLONE_NEWPID 0x20000000 /* New pid namespace */
  #define CLONE_NEWNET 0x40000000 /* New network namespace */
    不同类型的命名空间的作用:
 
    IPC:用于隔离进程间通讯所需的资源( System V IPC, POSIX message queues),PID命名空间和IPC命名空间可以组合起来用,同一个IPC名字空间内的进程可以彼此看见,允许进行交互,不同空间进程无法交互
 
    Network:Network Namespace为进程提供了一个完全独立的网络协议栈的视图。包括网络设备接口,IPv4和IPv6协议栈,IP路由表,防火墙规则,sockets等等。一个Network Namespace提供了一份独立的网络环境,就跟一个独立的系统一样。
 
 
    PID::linux通过命名空间管理进程号,同一个进程,在不同的命名空间进程号不同!进程命名空间是一个父子结构,子空间对于父空间可见。
 
    User:用于隔离用户
 
    UTS:用于隔离主机名
   三、UTS命名空间
    UTS命名空间几乎不需要特别的处理,因为它只需要简单量,没有层次组织。所有相关信息都汇集到下列结构的一个实例中。在utsname.h文件内:
 
  struct uts_namespace {
   struct new_utsname name;
   struct user_namespace *user_ns;
   struct ucounts *ucounts;
   struct ns_common ns;} __randomize_layout;
    uts_namespace所提供的属性信息本身包含在struct new_utsname中:
 
  struct oldold_utsname {
   char sysname[9];
   char nodename[9];
   char release[9];
   char version[9];
   char machine[9];};#define __NEW_UTS_LEN 64struct old_utsname {
   char sysname[65];
   char nodename[65];
   char release[65];
   char version[65];
   char machine[65];};struct new_utsname {
   char sysname[__NEW_UTS_LEN + 1];
   char nodename[__NEW_UTS_LEN + 1];
   char release[__NEW_UTS_LEN + 1];
   char version[__NEW_UTS_LEN + 1];
   char machine[__NEW_UTS_LEN + 1];
   char domainname[__NEW_UTS_LEN + 1];}
    各个字符串分别存储了系统的名称( Linux…)、内核发布版本、机器名,等等。使用uname工具可以取得这些属性的当前值,也可以在/proc/sys/kernel/中看到
 
  z@z-virtual-machine:~$ cat /proc/sys/kernel/ostype
  Linux
  z@z-virtual-machine:~$ cat /proc/sys/kernel/osrelease5.3.0-40-generic
    初始设置保存在init_uts_ns中,在init/version.c文件内:
 
  struct uts_namespace init_uts_ns = {
   .ns.count = REFCOUNT_INIT(2),
   .name = {
   .sysname = UTS_SYSNAME,
   .nodename = UTS_NODENAME,
   .release = UTS_RELEASE,
   .version = UTS_VERSION,
   .machine = UTS_MACHINE,
   .domainname = UTS_DOMAINNAME,
   },
   .user_ns = &init_user_ns,
   .ns.inum = PROC_UTS_INIT_INO,#ifdef CONFIG_UTS_NS
   .ns.ops = &utsns_operations,#endif};

(编辑:武林网)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表