Linux Namespace机制简介

最近Docker技术越来越受到关注,作为Docker中很重要的一项技术,Namespace也就经常在Docker的简介里面看到。

在这里总结一下它的内部机制。也解决一下自己原来的一些疑惑。

Namespace是什么:

C++中的Namespace:

首先,先提一下Namespace是什么。最早知道这个名词是在学习C++语言的时候。由于现在的系统越来越复杂,代码中不同的模块就可能使用相同变量,于是就出现了Namespace,来对全局作用域进行划分

比如C++的标注库都定义在STD Namespace中,需要使用时,就可以指定STD Namespace。当我们写一个类,类函数也需要使用namespace来指明这是属于哪一个类的函数。

Linux的Namespasce:

Linux Namespaces是一种轻量级的虚拟化形式。操作系统在内存,CPU上,已经使用了虚拟化的技术,让每个进程都认为是自己独占了内存和CPU。但像存储,磁盘,信号等,一些资源,操作系统并没有将其隔离开。

namespace则是将这类资源也隔离开来。使得进程只能看到自己的资源视图。这个功能加上Cgroup,就可以实现一个轻量级的虚拟机。这对于提高主机资源利用率很有用。如果说KVM这类虚拟机是为了隔离,而容器技术更多是为了共享。

Namespace原理:

对于内核来说,进程是由task_struct结构体来控制。所以Namespace肯定会和task_struct有关联。在task_struct中,定义了一个nsproxy的结构体指针。

nsproxy结构体:

1 struct task_struct {
2 ……..
3 /* namespaces */
4          struct nsproxy *nsproxy;
5 …….
6 }

nsproxy则是定义namespace的结构体。

01 /* 'count' 是task引用namspace的计数,这是通过nsproxy指向的计数。
02  * nsproxy被共用所有namespace的tasks所共享。只要一个namespace被clone或者不被使用,那么nsproxy就会被copy。
03 */
04 struct nsproxy {
05          atomic_t count;
06          struct uts_namespace *uts_ns;     //
07          struct ipc_namespace *ipc_ns;
08          struct mnt_namespace *mnt_ns;
09          struct pid_namespace *pid_ns;
10          <strong>struct</strong> user_namespace *user_ns;
11          struct net             *net_ns;
12 };
  1. uts_namespace结构体主要是包含了运行内核的名称、版本、底层体系结构类型等信息。UTS是UNIX Timesharing System的简称。
  2. *ipc_namespace指向保存在struct ipc_namespace中的所有与进程间通信(IPC)有关的信息。
  3. *mnt_namespace指向的是已经装载的文件系统的视图,在struct mnt_namespace中给出。
  4. *pid_ns_for_children指向有关进程ID的信息,由struct pid_namespace提供。
  5. user_ns 这个在新的3.8内核中实现。
  6. struct net_ns包含所有网络相关的命名空间参数。

默认nsproxy:

init_nsproxy是和task一起初始化的。除了mnt_ns 没有进行初始化,其余的namespace都进行了系统默认初始化。

创建新的Namspace:

如果要进程有独立的Namespace,可以使用系统调用clone().使用flag标记来设置

1 int clone(int (*fn)(void *), void *child_stack, int flags, void *arg)
  1. fn 是指向函数的指针。
  2. child_stack是运行的栈。需要传尾指针,因为栈是反着的。
  3. flag 就是设置namespace的地方。
  4. arg 是函数运行的参数。

当然,这个函数并非系统调用,这是glibc的函数。内核中真正工作的是do_fork函数。

do_fork函数会调用copy_process函数,在进行flag检查之后,里面会调用copy_namespaces.

这个函数会给task初始化一个新的nsproxy,然后对nsproxy里面的每个namespace结构体进行创建。

1 int copy_namespaces(unsigned long flags, struct task_struct *tsk);

进入存在的Namespace:

在刚开始用docker时,发现可以使用docker exec 来进入一个运行中的容器,对其操作。

如果是Cgroup,只需要找到对应挂在目录,echo进程pid到tasks里即可。但Namespace现在还没有这种设计。

另外,要进入一个已知的namespace还需要一个标识。不然,进入哪个Namespace呢。

1 /proc/[pid]/ns

这个时候,Linux一切皆文件的设计就体现出了它的优势。我们可以直接通过proc中的ns文件来获取这个Namespa的标示。Cgroup的设置也能通过proc中的文件看出。

1 int setns(int fd, int nstype);
  • 参数fd表示我们要加入的namespace的文件描述符。
  • nstype是用于校验的,传入0就是不校验。

setns之后,就可以通过exec系列的函数来运行需要的程序了。for会继承其父进程的Namespace。

参考:

http://blog.chinaunix.net/uid-20788636-id-4479145.html

Docker基础技术:Linux Namespace(上)

Docker基础技术:Linux Namespace(下)

http://lwn.net/Articles/531114/

 

转载请注明:旅途@KryptosX » Linux Namespace机制简介

时间: 2025-01-21 04:12:22

Linux Namespace机制简介的相关文章

Docker基础技术:Linux Namespace(上)

时下最热的技术莫过于Docker了,很多人都觉得Docker是个新技术,其实不然,Docker除了其编程语言用go比较新外,其实它还真不是个新东西,也就是个新瓶装旧酒的东西,所谓的The New "Old Stuff".Docker和Docker衍生的东西用到了很多很酷的技术,我会用几篇 文章来把这些技术给大家做个介绍,希望通过这些文章大家可以自己打造一个山寨版的docker. 当然,文章的风格一定会尊重时下的"流行"--我们再也没有整块整块的时间去看书去专研,而我

Docker基础技术:Linux Namespace【上】

点点收获: //之前发现Coolshell上好久不更新了, 博主果然去搞大业去了,只恨这几篇文章看到太晚了啊~太厉害了. 1.  clone(), unshare(), setns()初识; 主要是š三个系统调用 šclone() - 实现线程的系统调用,用来创建一个新的进程,并可以通过设计上述参数达到隔离. šunshare() - 使某进程脱离某个namespace šsetns() - 把某进程加入到某个namespace 2.  学习了一个命令 -- ipcs -- report XSI

Docker应用容器基础技术:Linux Namespace 学习教程

我们开始.先从Linux Namespace开始.  简介 Linux Namespace是Linux提供的一种内核级别环境隔离的方法.不知道你是否还记得很早以前的Unix有一个叫chroot的系统调用通过修改根目录把用户jail到一个特定目录下chroot提供了一种简单的隔离模式chroot内部的文件系统无法访问外部的内容.Linux Namespace在此基础上提供了对UTS.IPC.mount.PID.network.User等的隔离机制. 举个例子我们都知道Linux下的超级父亲进程的P

《自己动手写Docker》书摘之一: Linux Namespace

Linux Namespace 介绍 我们经常听到说Docker 是一个使用了Linux Namespace 和 Cgroups 的虚拟化工具,但是什么是Linux Namespace 它在Docker内是怎么被使用的,说到这里很多人就会迷茫,下面我们就先介绍一下Linux Namespace 以及它们是如何在容器里面使用的. 概念 Linux Namespace 是kernel 的一个功能,它可以隔离一系列系统的资源,比如PID(Process ID),User ID, Network等等.一

面向 DBA 的 Linux Shell 脚本简介

http://www.itpub.net/showthread.php?s=&threadid=720028 面向 DBA 的 Linux Shell 脚本简介 7 年前,Oracle 发布了 Linux 上的第一个商业数据库.从那时起,Oracle.Red Hat 和 Novell/SUSE 就不断地合作更改 Linux 内核,从而提高数据库和应用程序的性能.正因为这样,用于 Linux 的 Oracle 数据库 10g 才包含了与操作系统紧密相关的许多增强功能.DBA 比以往任何时候更需要了

Docker 基础技术:Linux Namespace(下)

在 Docker基础技术:Linux Namespace(上篇)中我们了解了,UTD.IPC.PID.Mount 四个namespace,我们模仿Docker做了一个相当相当山寨的镜像.在这一篇中,主要想向大家介绍Linux的User和Network的Namespace. 好,下面我们就介绍一下还剩下的这两个Namespace. User Namespace User Namespace主要是用了CLONE_NEWUSER的参数.使用了这个参数后,内部看到的UID和GID已经与外部不同了,默认显

利用linux信号机制调试段错误(Segment fault)

在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止.如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过串口.显示器可以查看消息,只要程序运行,通过GDB调试工具即可捕捉产生segment fault的具体原因.但是不知大家有没有想法,当程序运行在嵌入式设备上时,你所面临资源的缺乏,你没有串口打印信息,没有显示器可查看,你不知道程序运行的状态,如果程序的产生segment falut这种bug发生的周

定制和监视比较不同的Linux启动机制

您可以将 Linux 系统启动过程(从启动电源到让系统完全运行)看作两个概念性阶段: 从设备引导,加载并初始化 Linux 内核 启动用户空间应用程序(包括服务器进程),挂载另外的文件系统,执行另外的内核配置与定制项,并提供对额外设备的访问权限 第一阶段中的基本步骤已经在名为 "深入理解 Linux 的启动过程" 的 developerWorks 文章中讲述过了.这些步骤多年来变化不大,包括使用 GRand Unified Bootloader 2 (GRUB 2),初始 RAM 磁盘

Linux GRUB2配置简介

学习 GRUB 引导加载程序是如何预备你的系统并启动操作系统内核的. 自从上个月为我的文章<Linux 引导和启动过程简介>做研究开始,我对更深入了解 GRUB2 产生了兴趣.这篇文章提供了配置 GRUB2 的简要介绍.为了简便起见,我大多数情况下会使用 GRUB 指代 GRUB2. GRUB GRUB 来自 GRand Unified Bootloader 的缩写.它的功能是在启动时从 BIOS 接管掌控.加载自身.加载 Linux 内核到内存,然后再把执行权交给内核.一旦内核开始掌控,GR