Linux Namespace系列(01):Namespace概述

Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。

下面的所有例子都在ubuntu-server-x86_64 16.04下执行通过

Linux内核支持的namespaces

目前,Linux内核里面实现了7种不同类型的namespace。

名称        宏定义             隔离内容
Cgroup      CLONE_NEWCGROUP   Cgroup root directory (since Linux 4.6)
IPC         CLONE_NEWIPC      System V IPC, POSIX message queues (since Linux 2.6.19)
Network     CLONE_NEWNET      Network devices, stacks, ports, etc. (since Linux 2.6.24)
Mount       CLONE_NEWNS       Mount points (since Linux 2.4.19)
PID         CLONE_NEWPID      Process IDs (since Linux 2.6.24)
User        CLONE_NEWUSER     User and group IDs (started in Linux 2.6.23 and completed in Linux 3.8)
UTS         CLONE_NEWUTS      Hostname and NIS domain name (since Linux 2.6.19)

注意: 由于Cgroup namespace在4.6的内核中才实现,并且和cgroup v2关系密切,现在普及程度还不高,比如docker现在就还没有用它,所以在namespace这个系列中不会介绍Cgroup namespace。

查看进程所属的namespaces

系统中的每个进程都有/proc/[pid]/ns/这样一个目录,里面包含了这个进程所属namespace的信息,里面每个文件的描述符都可以用来作为setns函数(后面会介绍)的参数。

#查看当前bash进程所属的namespace
dev@ubuntu:~$ ls -l /proc/$$/ns     
total 0
lrwxrwxrwx 1 dev dev 0 7月 7 17:24 cgroup -> cgroup:[4026531835] #(since Linux 4.6)
lrwxrwxrwx 1 dev dev 0 7月 7 17:24 ipc -> ipc:[4026531839]       #(since Linux 3.0)
lrwxrwxrwx 1 dev dev 0 7月 7 17:24 mnt -> mnt:[4026531840]       #(since Linux 3.8)
lrwxrwxrwx 1 dev dev 0 7月 7 17:24 net -> net:[4026531957]       #(since Linux 3.0)
lrwxrwxrwx 1 dev dev 0 7月 7 17:24 pid -> pid:[4026531836]       #(since Linux 3.8)
lrwxrwxrwx 1 dev dev 0 7月 7 17:24 user -> user:[4026531837]     #(since Linux 3.8)
lrwxrwxrwx 1 dev dev 0 7月 7 17:24 uts -> uts:[4026531838]       #(since Linux 3.0)
  • 上面每种类型的namespace都是在不同的Linux版本被加入到/proc/[pid]/ns/目录里去的,比如pid namespace是在Linux 3.8才被加入到/proc/[pid]/ns/里面,但这并不是说到3.8才支持pid namespace,其实pid namespace在2.6.24的时候就已经加入到内核了,在那个时候就可以用pid namespace了,只是有了/proc/[pid]/ns/pid之后,使得操作pid namespace更方便了

  • 虽然说cgroup是在Linux 4.6版本才被加入内核,可是在Ubuntu 16.04上,尽管内核版本才4.4,但也支持cgroup namespace,估计应该是Ubuntu将4.6的cgroup namespace这部分代码patch到了他们的4.4内核上。

  • 以ipc:[4026531839]为例,ipc是namespace的类型,4026531839是inode number,如果两个进程的ipc namespace的inode number一样,说明他们属于同一个namespace。这条规则对其他类型的namespace也同样适用。

  • 从上面的输出可以看出,对于每种类型的namespace,进程都会与一个namespace ID关联。

跟namespace相关的API

和namespace相关的函数只有三个,这里简单的看一下,后面介绍UTS namespace的时候会有详细的示例

clone: 创建一个新的进程并把他放到新的namespace中

int clone(int (*child_func)(void *), void *child_stack
            , int flags, void *arg);

flags: 
    指定一个或者多个上面的CLONE_NEW*(当然也可以包含跟namespace无关的flags), 
    这样就会创建一个或多个新的不同类型的namespace, 
    并把新创建的子进程加入新创建的这些namespace中。

setns: 将当前进程加入到已有的namespace中

int setns(int fd, int nstype);

fd: 
    指向/proc/[pid]/ns/目录里相应namespace对应的文件,
    表示要加入哪个namespace

nstype:
    指定namespace的类型(上面的任意一个CLONE_NEW*):
    1. 如果当前进程不能根据fd得到它的类型,如fd由其他进程创建,
    并通过UNIX domain socket传给当前进程,
    那么就需要通过nstype来指定fd指向的namespace的类型
    2. 如果进程能根据fd得到namespace类型,比如这个fd是由当前进程打开的,
    那么nstype设置为0即可

unshare: 使当前进程退出指定类型的namespace,并加入到新创建的namespace(相当于创建并加入新的namespace)

int unshare(int flags);

flags:
    指定一个或者多个上面的CLONE_NEW*,
    这样当前进程就退出了当前指定类型的namespace并加入到新创建的namespace

clone和unshare的区别

clone和unshare的功能都是创建并加入新的namespace, 他们的区别是:

  • unshare是使当前进程加入新的namespace

  • clone是创建一个新的子进程,然后让子进程加入新的namespace,而当前进程保持不变

其它

当一个namespace中的所有进程都退出时,该namespace将会被销毁。当然还有其他方法让namespace一直存在,假设我们有一个进程号为1000的进程,以ipc namespace为例:

  1. 通过mount --bind命令。例如mount --bind /proc/1000/ns/ipc /other/file,就算属于这个ipc namespace的所有进程都退出了,只要/other/file还在,这个ipc namespace就一直存在,其他进程就可以利用/other/file,通过setns函数加入到这个namespace

  2. 在其他namespace的进程中打开/proc/1000/ns/ipc文件,并一直持有这个文件描述符不关闭,以后就可以用setns函数加入这个namespace。

参考


Linux程序员
专注Linux相关技术
3.7k 声望
1.6k 粉丝
0 条评论
推荐阅读
走进docker(07):docker start命令背后发生了什么?
在上一篇介绍过了docker create之后,这篇来看看docker start是怎么根据create之后的结果运行容器的。 启动容器 在这里我们先启动上一篇中创建的那个容器,然后看看docker都干了些什么。 {代码...} start的大概流...

public08218阅读 14.1k评论 5

工具篇:iTerm与Zsh
iTerm2支持许多的主题配色,可以自己定义,也可以参考网上现成的主题配色。我个人比较喜欢draculatheme配色。支持item,vim,phpstorm , 下方存在主题官网路径,按照教程安装即可。

super白4阅读 4.8k

深入剖析容器网络和 iptables
Docker 能为我们提供很强大和灵活的网络能力,很大程度上要归功于与 iptables 的结合。在使用时,你可能没有太关注到 iptables 的作用,这是因为 Docker 已经帮我们自动完成了相关的配置。

张晋涛3阅读 1.3k

封面图
麒麟操作系统 (kylinos) 从入门到精通 - 常用软件安装 - 第三篇 常用软件安装(windows下的习惯)
本篇内容大部分从应用商店进行安装,部分通过官网下载,少部分通过命令行安装。1.原生应用1.1钉钉1.2飞书1.3 蓝信1.4 腾讯文档1.5 金山文档1.6 搜狗输入法(拼音)1.7 五笔输入法1.8 libreoffice官方也带了WPS,...

码上世界3阅读 7.6k评论 17

封面图
.记一次使用gdb诊断gc问题全过程
上次解决了GC长耗时问题后,系统果然平稳了许多,这是之前的文章《GC耗时高,原因竟是服务流量小?》 然而,过了一段时间,我检查GC日志时,又发现了一个GC问题,如下: 从这个图中可以发现,我们GC有一些尖峰,...

扣钉日记2阅读 675

封面图
麒麟操作系统 (kylinos) 从入门到精通 - 办公环境 - 第十三篇 字体安装与windows字体的利用
正常情况下,系统下的wps或libreoffice用到的字体都已默认安装。但有时候一些ttf字体或者microsoft office下一些字体需要安装。我们可以在安装好office、acrobat之后,将C:\windows\Fonts文件夹中的字体(我是win...

码上世界2阅读 4.1k

封面图
麒麟操作系统 (kylinos) 从入门到精通 - 影音娱乐- 第三十篇 利用PKS观看电视台(IPTV)直播
类别:笔记本型号:中国长城 UF712硬件平台:飞腾处理器(ArmV8 指令集)系统:银河麒麟操作系统 V10 SP1(2203) 关键词:信创,麒麟系统,linux,PKS,银河麒麟,飞腾,arm64,arm,湖南卫视,中央电视台,电视直播,iptv

码上世界1阅读 3.9k

封面图
3.7k 声望
1.6k 粉丝
宣传栏