linux内核轻量级虚拟化之Namespace
来源:互联网 发布:zsysecdesk是什么软件 编辑:程序博客网 时间:2024/06/06 01:05
一.什么是namespace
Namespace,命名空间,顾名思义,就是不同的名字空间,打个简单的比方,进程在a空间是叫a进程,在b空间也就可能叫b进程。为什么要有命名空间呢?主要是满足虚拟化的一些需求。试想,如果有一台机器,不管它是个人pc还是服务器,或是网络交换机,路由器,一般情况下,它也就被一个用户使用。但是如果某一天,另外一个用户也要使用同样的机器,一种方法是再买一个机器,装上同样的linux系统,但是还有一种更好的方法,就是使用容器(container),每个用户有属于自己的容器,而且容器之间相互隔离,而namespace就是实现容器的一种手段。
二.Namespace的数据结构
首先,namespace是针对进程而言的,所以在task_struct中有一个指向结构nsproxy的指针,这个就是进程的名字空间,下面看一下nsproxy的结构:/*
* A structure to contain pointers to all per-process
* namespaces - fs (mount), uts, network, sysvipc, etc.
*
* '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;
struct user_namespace *user_ns;
struct net *net_ns;
};
可见一个进程有多维的名字空间,比如UTS,PID,NET,USER等等,其中比较重要和复杂的就是pid namespace了。由于在不同的名字空间里进程有不同的pid,如此一来,进程的pid就分成了两种:一种是global pid,另一种是local pid,所谓的global pid就是内核自己用的pid,也是initial namespace中的pid。Local pid就是派生出来的子命名空间的pid,由此也看出,pid namespace是一种树状的结构:
父空间可以看到所有子空间的进程,而两个子空间互相不可见。这一点也可以从pid_namespace中看出:
struct pid_namespace {
struct kref kref;//此pid namespace的引用计数
struct pidmap pidmap[PIDMAP_ENTRIES];//pid的bit表, bit为0表示空闲的pid号
int last_pid;//最后一次分配的pid,用于alloc_pidmap时快速找到下一个空闲的pid
struct task_struct *child_reaper;//用于回收僵尸进程
struct kmem_cache *pid_cachep;//软件cache,用于分配pid结构
int level;//从init pid namespace开始数,第几级
struct pid_namespace *parent;//父pid namespace
#ifdef CONFIG_PROC_FS
struct vfsmount *proc_mnt;
#endif
};
另外还有两个比较重要的数据结构:第一,内核所见的pid
struct pid
{
atomic_t count;
/* lists of tasks that use this pid */
struct hlist_head tasks[PIDTYPE_MAX];//此pid对应的task
struct rcu_head rcu;
int level;//此pid对应的级数,也是下面一个域的真正的数组下标
struct upid numbers[1];从1到level各个namespace中的pid
};
第二,属于具体某个空间的pid:
struct upid {
/* Try to keep pid_chain in the same cacheline as nr for find_pid */
int nr;
struct pid_namespace *ns;
struct hlist_node pid_chain;
};
具体数据结构组织如右图:
三.Pid namespace的功能
主要需要实现两个功能:
1.指定一个namespace和一个pid 值,找到相应的task_struct结构
2.指定一个task_struct结构和一个namespace,找到对应的pid 值。
第一个功能实现:
首先找到相应的pid结构:
struct pid *find_pid_ns(int nr, struct pid_namespace *ns)
{
struct hlist_node *elem;
struct upid *pnr;
hlist_for_each_entry_rcu(pnr, elem,
&pid_hash[pid_hashfn(nr, ns)], pid_chain)
if (pnr->nr == nr && pnr->ns == ns)
return container_of(pnr, struct pid,
numbers[ns->level]);
return NULL;
}
然后通过pid->tasks找到对应的task结构
第二个的功能实现:先找到pid结构
static inline struct pid *task_pid(struct task_struct *task)
{
return task->pids[PIDTYPE_PID].pid;
}
然后找到对应的upid结构,从而发现对应namespace的pid值
pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
{
struct upid *upid;
pid_t nr = 0;
if (pid && ns->level <= pid->level) {
upid = &pid->numbers[ns->level];
if (upid->ns == ns)
nr = upid->nr;
}
return nr;
}
四.总结
Namespace是linux内核轻量级虚拟化的重要的部分,可以为后续虚拟化提供基石,很多开源的虚拟化项目例如openvz也利用了linux内核的pid namespace的技术。所以,将其研究透彻很有必要,这样也为以后的研究打下基础。
- linux内核轻量级虚拟化之Namespace
- Linux Container-内核轻量级虚拟化技术
- Linux内核中namespace之PID namespace
- Linux内核-容器之namespace
- 虚拟化–操作系统级 LXC Linux Containers内核轻量级虚拟化技术
- Linux内核虚拟化之KVM
- linux 网络虚拟化:network namespace 简介
- Linux内核中的Namespace
- Linux内核中的Namespace
- Linux内核中的Namespace
- Linux内核namespace机制
- Linux内核namespace机制
- Linux内核中的Namespace
- linux内核虚拟化之路(一) cgroup机制
- LXC 轻量级虚拟化
- Linux网络虚拟化:network namespace的学习
- Linux内核具体体系结构之虚拟文件系统
- Linux内核具体体系结构之虚拟文件系统
- C++中extern “C”含义深层探索
- 这是第一篇博客,作为测试
- hdu 2391 Filthy Rich
- MVC模式基本理解
- Matlab高性能编程——代码优化和并行计算
- linux内核轻量级虚拟化之Namespace
- 贴图透明特效的实现
- Cocos2d—X游戏开发之CCToggle(菜单标签切换)CCControlSwitch(开关切换)(十二)
- dl-ssl.google.com无法打开
- MyEclipse快捷键大全
- 重写、覆盖、重载、多态几个概念的区别分析
- HDU 统计难题
- 注册表键值快速定位
- 线段树求矩形并模板