返回顶部
首页 > 资讯 > 操作系统 >Linux中的命名空间
  • 818
分享到

Linux中的命名空间

2023-06-13 00:06:09 818人浏览 泡泡鱼
摘要

本篇内容介绍了“linux中的命名空间 ”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!背景从Linux 2.6.24版的内核开始,Linux

本篇内容介绍了“linux中的命名空间 ”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

背景

从Linux 2.6.24版的内核开始,Linux 就支持6种不同类型的命名空间。它们的出现,使用户创建的进程能够与系统分离得更加彻底,从而不需要使用更多的底层虚拟化技术。

  •     CLONE_NEWIPC: 进程间通信(IPC)的命名空间,可以将 SystemV 的 IPC 和 POSIX 的消息队列独立出来。
        CLONE_NEWPID: 进程命名空间。空间内的PID 是独立分配的,意思就是命名空间内的虚拟 PID 可能会与命名空间外的 PID 相冲突,于是命名空间内的 PID 映射到命名空间外时会使用另外一个 PID。比如说,命名空间内第一个 PID 为1,而在命名空间外就是该 PID 已被 init 进程所使用。
        CLONE_NEWNET: 网络命名空间,用于隔离网络资源(/proc/net、IP 地址、网卡、路由等)。后台进程可以运行在不同命名空间内的相同端口上,用户还可以虚拟出一块网卡。
        CLONE_NEWNS: 挂载命名空间,进程运行时可以将挂载点与系统分离,使用这个功能时,我们可以达到 chroot 的功能,而在安全性方面比 chroot 更高。
        CLONE_NEWUTS: UTS 命名空间,主要目的是独立出主机名和网络信息服务(NIS)。
        CLONE_NEWUSER: 用户命名空间,同进程 ID 一样,用户 ID 和组 ID 在命名空间内外是不一样的,并且在不同命名空间内可以存在相同的 ID。

下面我们介绍一下进程命名空间和网络命名空间。
进程命名空间

本文用 C 语言介绍上述概念,因为演示进程命名空间的时候需要用到 C 语言。下面的测试过程在 Debian 6 和 Debian 7 上执行。首先,在栈内分配一页内存空间,并将指针指向内存页的末尾。这里我们使用 alloca() 函数来分配内存,不要用 malloc() 函数,它会把内存分配在堆上。

   

代码如下:

void *mem = alloca(sysconf(_SC_PAGESIZE)) + sysconf(_SC_PAGESIZE);

然后使用 clone() 函数创建子进程,传入我们的子栈空间地址 "mem",并指定命名空间的标记。同时我们还指定“callee”作为子进程运行的函数。

   

代码如下:

mypid = clone(callee, mem, SIGCHLD | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | CLONE_FILES, NULL);

clone 之后我们要在父进程中等待子进程先退出,否则的话,父进程会继续运行下去,并马上进程结束,留下子进程变成孤儿进程:

   

代码如下:

while (waitpid(mypid, &r, 0) < 0 && errno == EINTR)
   {
       continue;
   }

最后当子进程退出后,我们会回到 shell 界面,并返回子进程的退出码。

   

代码如下:

if (WIFEXITED(r))
   {
       return WEXITSTATUS(r);
   }
   return EXIT_FAILURE;

上文介绍的 callee 函数功能如下:

   

代码如下:

static int callee()
   {
       int ret;
       mount("proc", "/proc", "proc", 0, "");
       setgid(u);
       setgroups(0, NULL);
       setuid(u);
       ret = execl("/bin/bash", "/bin/bash", NULL);
       return ret;
   }

程序挂载了 /proc 文件系统,设置用户 ID 和组 ID,值都为“u”,然后运行 /bin/bash 程序,LXC 是一个操作系统级的虚拟化工具,使用 cgroups 和命名空间来完成资源的分离。现在我们把所有代码放在一起,变量“u”的值设为65534,在 Debian 系统中,这是“nobody”和“nogroup”:

   

代码如下:

#define _GNU_SOURCE
   #include <unistd.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <sys/types.h>
   #include <sys/wait.h>
   #include <sys/mount.h>
   #include <grp.h>
   #include <alloca.h>
   #include <errno.h>
   #include <sched.h>
   static int callee();
   const int u = 65534;
   int main(int argc, char *argv[])
   {
       int r;
       pid_t mypid;
       void *mem = alloca(sysconf(_SC_PAGESIZE)) + sysconf(_SC_PAGESIZE);
       mypid = clone(callee, mem, SIGCHLD | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | CLONE_FILES, NULL);
       while (waitpid(mypid, &r, 0) < 0 && errno == EINTR)
       {
           continue;
       }
       if (WIFEXITED(r))
       {
           return WEXITSTATUS(r);
       }
       return EXIT_FAILURE;
   }
   static int callee()
   {
       int ret;
       mount("proc", "/proc", "proc", 0, "");
       setgid(u);
       setgroups(0, NULL);
       setuid(u);
       ret = execl("/bin/bash", "/bin/bash", NULL);
       return ret;
   }

执行以下命令来运行上面的代码:

   

代码如下:

root@w:~/pen/tmp# gcc -O -o ns.c -Wall -Werror -ansi -c89 ns.c
   root@w:~/pen/tmp# ./ns
   nobody@w:~/pen/tmp$ id
   uid=65534(nobody) gid=65534(nogroup)
   nobody@w:~/pen/tmp$ ps auxw
   USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
   nobody       1  0.0  0.0   4620  1816 pts/1    S    21:21   0:00 /bin/bash
   nobody       5  0.0  0.0   2784  1064 pts/1    R+   21:21   0:00 ps auxw
   nobody@w:~/pen/tmp$

注意上面的结果,UID 和 GID 被设置成 nobody 和 nogroup 了,特别是 ps 工具只输出两个进程,它们的 ID 分别是1和5(LCTT注:这就是上文介绍 CLONE_NEWPID 时提到的功能,在线程所在的命名空间内,进程 ID 可以为1,映射到命名空间外是另外一个 PID;而命名空间外的 ID 为1的进程一直是 init)。
网络命名空间

接下来轮到使用 ip netns 来设置网络的命名空间。第一步先确定当前系统没有命名空间:

   

代码如下:

root@w:~# ip netns list
   Object "netns" is unknown, try "ip help".

如果报了上述错误,你需要更新你的系统内核,以及 ip 工具程序。这里假设你的内核版高于2.6.24,ip 工具版本也差不多,高于2.6.24(LCTT注:ip 工具由 iproute 安装包提供,此安装包版本与内核版本相近)。更新好后,ip netns list 在没有命名空间存在的情况下不会输出任务信息。加个名为“ns1”的命名空间看看:

   

代码如下:

root@w:~# ip netns add ns1
   root@w:~# ip netns list
   ns1

列出网卡:

   

代码如下:

root@w:~# ip link list
   1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT
       link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   2: eth0:  mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT qlen 1000
       link/ether 00:0c:29:65:25:9e brd ff:ff:ff:ff:ff:ff

创建新的虚拟网卡,并加到命名空间。虚拟网卡需要成对创建,互相关联&mdash;&mdash;就像交叉电缆一样:

   

代码如下:

root@w:~# ip link add veth0 type veth peer name veth2
   root@w:~# ip link list
   1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT
       link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   2: eth0:  mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT qlen 1000
       link/ether 00:0c:29:65:25:9e brd ff:ff:ff:ff:ff:ff
   3: veth2:  mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
       link/ether d2:e9:52:18:19:ab brd ff:ff:ff:ff:ff:ff
   4: veth0:  mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
       link/ether f2:f7:5e:e2:22:ac brd ff:ff:ff:ff:ff:ff

这个时候 ifconfig -a 命令也能显示新添加的 veth0 和 veth2 两块网卡。

很好,现在将这两份块网卡加到命名空间中去。注意一下,下面的 ip netns exec 命令用于将后面的命令在命名空间中执行(LCTT注:下面的结果显示了在 ns1 这个网络命名空间中,只存在 lo 和 veth2 两块网卡):

   

代码如下:

root@w:~# ip link set veth2 netns ns1
   root@w:~# ip netns exec ns1 ip link list
   1: lo:  mtu 65536 qdisc noop state DOWN mode DEFAULT
       link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   3: veth2:  mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
   link/ether d2:e9:52:18:19:ab brd ff:ff:ff:ff:ff:ff

这个时候 ifconfig -a 命令只能显示 veth0,不能显示 veth2,因为后者现在在 ns1 命名空间中。

如果想删除 veth0/veth2,可以执行下面的命令:

   

代码如下:

ip netns exec ns1 ip link del veth2

我们可以为 veth0 分配 IP 地址:

   

代码如下:

ifconfig veth0 192.168.5.5/24

在命名空间内为 veth2 分配 IP 地址:

   

代码如下:

ip netns exec ns1 ifconfig veth2 192.168.5.10/24 up

在命名空间内外执行 ip addr list 命令:

   

代码如下:

root@w:~# ip addr list
   1: lo:  mtu 65536 qdisc noqueue state UNKNOWN
       link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
       inet 127.0.0.1/8 scope host lo
       inet6 ::1/128 scope host
          valid_lft forever preferred_lft forever
   2: eth0:  mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
       link/ether 00:0c:29:65:25:9e brd ff:ff:ff:ff:ff:ff
       inet 192.168.3.122/24 brd 192.168.3.255 scope global eth0
       inet6 fe80::20c:29ff:fe65:259e/64 scope link
          valid_lft forever preferred_lft forever
   6: veth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
       link/ether 86:b2:c7:bd:c9:11 brd ff:ff:ff:ff:ff:ff
       inet 192.168.5.5/24 brd 192.168.5.255 scope global veth0
       inet6 fe80::84b2:c7ff:febd:c911/64 scope link
          valid_lft forever preferred_lft forever
   root@w:~# ip netns exec ns1 ip addr list
   1: lo:  mtu 65536 qdisc noop state DOWN
       link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   5: veth2:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
       link/ether 12:bd:b6:76:a6:eb brd ff:ff:ff:ff:ff:ff
       inet 192.168.5.10/24 brd 192.168.5.255 scope global veth2
       inet6 fe80::10bd:b6ff:fe76:a6eb/64 scope link
          valid_lft forever preferred_lft forever

在命名空间内外查看路由表:

   

代码如下:

root@w:~# ip route list
   default via 192.168.3.1 dev eth0  proto static
   192.168.3.0/24 dev eth0  proto kernel  scope link  src 192.168.3.122
   192.168.5.0/24 dev veth0  proto kernel  scope link  src 192.168.5.5
   root@w:~# ip netns exec ns1 ip route list
   192.168.5.0/24 dev veth2  proto kernel  scope link  src 192.168.5.10

最后,将虚拟网卡连到物理网卡上,我们需要用到桥接。这里做的是将 veth0 桥接到 eth0,而 ns1 命名空间内则使用 DHCP 自动获取 IP 地址:

   

代码如下:

root@w:~# brctl addbr br0
   root@w:~# brctl addif br0 eth0
   root@w:~# brctl addif br0 veth0
   root@w:~# ifconfig eth0 0.0.0.0
   root@w:~# ifconfig veth0 0.0.0.0
   root@w:~# dhclient br0
   root@w:~# ip addr list br0
   7: br0:  mtu 1500 qdisc noqueue state UP
       link/ether 00:0c:29:65:25:9e brd ff:ff:ff:ff:ff:ff
       inet 192.168.3.122/24 brd 192.168.3.255 scope global br0
       inet6 fe80::20c:29ff:fe65:259e/64 scope link
          valid_lft forever preferred_lft forever

为网桥 br0 分配的 IP 地址为192.168.3.122/24。接下来为命名空间分配地址:

   

代码如下:

root@w:~# ip netns exec ns1 dhclient veth2
   root@w:~# ip netns exec ns1 ip addr list
   1: lo:  mtu 65536 qdisc noop state DOWN
       link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   5: veth2:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
       link/ether 12:bd:b6:76:a6:eb brd ff:ff:ff:ff:ff:ff
       inet 192.168.3.248/24 brd 192.168.3.255 scope global veth2
       inet6 fe80::10bd:b6ff:fe76:a6eb/64 scope link
          valid_lft forever preferred_lft forever

现在, veth2 的 IP 被设置成 192.168.3.248/24 了。

“Linux中的命名空间 ”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: Linux中的命名空间

本文链接: https://lsjlt.com/news/263953.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Linux中的命名空间
    本篇内容介绍了“Linux中的命名空间 ”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!背景从Linux 2.6.24版的内核开始,Linux...
    99+
    2023-06-13
  • 【C++】命名空间 namespace 与 标准流 iostream ( 命名空间概念简介 | 命名空间定义 | 命名空间使用 | iostream 中的命名空间分析 )
    文章目录 一、命名空间 namespace1、命名空间基本概念2、名称概念4、C 语言的命名空间3、命名空间避免标识符冲突 二、命名空间定义1、命名空间基本概念2、命名空间定义语法3、代码示例 - 命名空间定义使用 三、命名...
    99+
    2023-08-20
    c++ namespace iostream 命名空间 标准流 原力计划
  • Linux的命名空间如何理解
    小编今天带大家了解Linux的命名空间如何理解,文中知识点介绍的非常详细。觉得有帮助的朋友可以跟着小编一起浏览文章的内容,希望能够帮助更多想解决这个问题的朋友找到问题的答案,下面跟着小编一起深入学习“Linux的命名空间如何理解”的知识吧。...
    99+
    2023-06-29
  • MyBatis Mapper.xml中的命名空间及命名方式
    目录Mapper.xml相关使用命名空间(Namespaces)命名解析MyBatis中mapper.xml命名空间错误项目场景问题描述原因分析解决方案Mapper.xml相关使用 ...
    99+
    2024-04-02
  • 详解PHP中的命名空间
    命名空间其实早在PHP5.3就已经出现了。不过大部分同学可能在各种框架的使用中才会接触到命名空间的内容,当然,现代化的开发也都离不开这些能够快速产出的框架。这次我们不从框架的角度,仅...
    99+
    2024-04-02
  • .net core中的System.Buffers命名空间
    最近研究了一下.net core 2.1的基础类库,发现它引入了一个System.Buffers名字空间,里面提供了一系列比较实用的对象,便简单的管中窥豹浏览一下。 ArrayPoo...
    99+
    2024-04-02
  • python-命名空间
    通俗的来说,Python中所谓的命名空间可以理解为一个容器。在这个容器中可以装许多标识符。不同容器中的同名的标识符是不会相互冲突的。理解python的命名空间需要掌握三条规则:第一,赋值(包括显式赋值和隐式赋值)产生标识符,赋值的地点决定标...
    99+
    2023-01-31
    空间 python
  • python命名空间
    python使用命名空间记录变量。python中的命名空间就像是一个dict,key是变量的名字,value是变量的值。 python中,每个函数都有一个自己的命名空间,叫做local namespace,它记录了函数的变量。 ...
    99+
    2023-01-31
    空间 python
  • C++的命名空间详解
    目录C++ | C++命名空间C++命名空间定义命名空间实例1:using 指令实例2:实例3:不连续的命名空间嵌套的命名空间实例4:实例5:笔记:实例6:实例7:总结C++ | C...
    99+
    2024-04-02
  • vuex命名空间的使用
    目录Vuex由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。 因此,Vuex 允许我们将 store 分割成模...
    99+
    2024-04-02
  • C++空间命名的使用
    目录前言一、命名空间二、命名空间定义1.嵌套性2.和并性3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。 ps:一个工程中的test.h和上面te...
    99+
    2023-01-28
    C++ 空间命名
  • C++中的命名空间详细介绍
    目录命名空间的特性声明命名空间和命名空间成员全局命名空间不连续命名空间嵌套命名空间using声明和using编译指令命名空间别名综合代码示例总结命名空间的特性 首先熟悉一下命名空间的...
    99+
    2024-04-02
  • php中的子命名空间是什么
    这篇文章主要介绍“php中的子命名空间是什么”,在日常操作中,相信很多人在php中的子命名空间是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”php中的子命名空间是什么”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-20
  • php中命名空间的调用顺序
    小编给大家分享一下php中命名空间的调用顺序,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!首先让我们看一个小例子。<phpnamespace A;...
    99+
    2023-06-20
  • C++中的命名空间实例分析
    这篇“C++中的命名空间实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++中的命名空间实例分析”文章吧。命名空间的...
    99+
    2023-06-29
  • C++中的命名空间怎么使用
    在C++中,命名空间(namespace)用于避免命名冲突,将全局作用域划分为不同的区域,使得不同的代码块可以使用相同的名称而不会发...
    99+
    2024-03-11
    C++
  • 怎么在命名空间中引入另一空间的元素
    这期内容当中小编将会给大家带来有关怎么在命名空间中引入另一空间的元素,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。空间引入方式:使用use关键字<phpnamespace n1;class...
    99+
    2023-06-08
  • C++ 命名空间详解
    目录一、C++ 命名空间1.默认NameSpace(Global&Function)2.语法规则1.声明 2.使用方法3.支持嵌套总结一、C++ 命名空间 命名空间...
    99+
    2024-04-02
  • TypeScript命名空间讲解
    目录1.定义和使用 1.1定义 1.2使用 2.拆分为多个文件 3.别名 前言: 命名空间namespace在TypeScript1.5版本之前是叫做内部模块 ,那是因为ES6中的...
    99+
    2024-04-02
  • 【C++】入门 --- 命名空间
    文章目录 🍪一、前言🍩1、C++简介🍩2、C++关键字 🍪二、命名冲突🍪三、命名空间🍩1、命名空间定义🍩2、命名空...
    99+
    2023-08-17
    c++ 命名空间 开发语言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作