虚拟化–操作系统级 LXC Linux Containers内核轻量级虚拟化技术

友情提示:非原文链接可能会影响您的阅读体验,欢迎查看原文。(http://blog.geekcome.com)原文地址:http://blog.geekcome.com/archives/288


软件平台:Ubuntu 14.04

容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好的在孤立的组之间有冲突的资源使用需求。与其它的虚拟化比較,这样既不须要指令级模拟。也不须要即时编译。

容器能够在寒心CPU本地运行指令,而不须要不论什么专门的解释机制。此外半虚拟化和系统调用替换的复杂性。

LXC的实现是基于内核中的namespace和cgroup实现的。

namespace:

和C++中的namespace概念类似。在Linux操作系统中,系统资源如:进程、用户账户、文件系统、网络都是属于某个namespace。

每个namespace下的资源对于其它的namespace资源是透明的,不可见的。由于在操作系统层上就会出现同样的pid的进程。多个同样uid的不同账号。

内核中的实现:

namespace是针对每个进程而言的,所以在task_struct结构的定义中有一个指向nsproxy的指针

1 /* namespaces */
2 struct nsproxy *nsproxy;

该结构体的定义例如以下:

01 /*
02  * A structure to contain pointers to all per-process
03  * namespaces - fs (mount), uts, network, sysvipc, etc.
04  *
05  * The pid namespace is an exception -- it's accessed using
06  * task_active_pid_ns.  The pid namespace here is the
07  * namespace that children will use.
08  *
09  * 'count' is the number of tasks holding a reference.
10  * The count for each namespace, then, will be the number
11  * of nsproxies pointing to it, not the number of tasks.
12  *
13  * The nsproxy is shared by tasks which share all namespaces.
14  * As soon as a single namespace is cloned or unshared, the
15  * nsproxy is copied.
16  */
17 struct nsproxy {
18     atomic_t count;
19     struct uts_namespace *uts_ns;
20     struct ipc_namespace *ipc_ns;
21     struct mnt_namespace *mnt_ns;
22     struct pid_namespace *pid_ns_for_children;
23     struct net       *net_ns;
24 };

当中第一个属性count表示的是该命名空间被进程引用的次数。后面的几个各自是不同类型的命名空间。以pid_namespace为例。

其结构例如以下所看到的:

01 struct pid_namespace {
02     struct kref kref;//引用计数
03     struct pidmap pidmap[PIDMAP_ENTRIES];//用于标记空暇的id号
04     struct rcu_head rcu;
05     int last_pid;//上一次分配的id号
06     unsigned int nr_hashed;
07     struct task_struct *child_reaper;//相当于全局的init进程,用于对僵尸进程进行回收
08     struct kmem_cache *pid_cachep;
09     unsigned int level;//namespace的层级
10     struct pid_namespace *parent;//上一级namespace指针
11 #ifdef CONFIG_PROC_FS
12     struct vfsmount *proc_mnt;
13     struct dentry *proc_self;
14 #endif
15 #ifdef CONFIG_BSD_PROCESS_ACCT
16     struct bsd_acct_struct *bacct;
17 #endif
18     struct user_namespace *user_ns;
19     struct work_struct proc_work;
20     kgid_t pid_gid;
21     int hide_pid;
22     int reboot; /* group exit code if this pidns was rebooted */
23     unsigned int proc_inum;
24 };

内核中的pid结构表示:

1 struct pid
2 {
3     atomic_t count;
4     unsigned int level;//pid相应的级数
5     /* lists of tasks that use this pid */
6     struct hlist_head tasks[PIDTYPE_MAX];//一个pid可能相应多个task_struct
7     struct rcu_head rcu;
8     struct upid numbers[1];//该结构是namespace中的详细的pid。从1到level各级别的namesapce,这里相当于一个指针。仅仅只是不须要再分配空间
9 };

上面的结构体就是内核中进程的标示符,能够用于标识内核中的tasks、process groups和sessions。这个结构体和详细的task通过hash来关联。通过详细的task相应的pid的值能够获得绑定的pid结构体。

属于详细的namespace的pid结构upid:

1 struct upid {
2     /* Try to keep pid_chain in the same cacheline as nr for find_vpid */
3     int nr;
4     struct pid_namespace *ns;
5     struct hlist_node pid_chain;
6 };

该结构体是用来获得结构体pid的详细的id,它仅仅对特定的namespace可见。会通过函数find_pid_ns(int nr,pid_namespace *ns)函数来获得详细的PID结构。

总体结构例如以下图:

虚拟化–操作系统级 LXC Linux Containers内核轻量级虚拟化技术

 

Cgroup:

Cgroup是control groups的缩写,是Linux内核提供的一种能够限制、记录、隔离进程组所使用的物理资源(CPU,内存,IO等等)的机制。Cgroup也是LXC位实现虚拟化所使用的资源管理的手段。

能够说没有Cgroup就没有LXC,也就没有Docker。

Cgroup提供的功能:

  • 限制进程组能够使用的资源数量。
上一篇:内核定时机制API之ns_to_timespec64 和 ns_to_timeval


下一篇:让DNS运行在容器中