第十三章 网络命名空间(内核源码实现)--基于Linux3.10

2023-11-10

下载地址《http://download.csdn.net/detail/shichaog/8620701》

有两篇翻译博文《Lxc之二—网络设置》和《linuxnamespace-之使用》;LXC文章中关于网络的设置是从用户空间配置的,从该文章可以知道网络命名空间的一些基本概念和其提供的功能。而《linuxnamespace-之使用》包括了网络命名空间管理、配置以及使用,这比LXC译文更接近网络命名空间的实现,但是都是基于用户空间的,这章是关于Linux网络命名空间内核源码。在Linux中,每一个网络空间都使用struct net表示。

13.1 命名空间创建

在当前Linux下,对进程而言一个命名空间包括五个具体的命名空间,mnt、uts、ipc、pid以及net,在os启动时,其会初始化一个称为init的初始命名空间,并将该命名空间给创建的进程,在后续创建进程时,将根据创建的flag确定是否创建新的命名空间。在图13.1.1中,进程1、2都指向了init命名空间,在创建进程3时,明确指定了复制网络命名空间,其它的命名空间依然会继承(copy)。


图13.1.1 命名空间和进程的组合

创建命名空间的系统调用如下,nstype是创建进程时指定的创建命名空间的标志。

kernel/nsproxy.c

239 SYSCALL_DEFINE2(setns, int, fd, int, nstype)
240 {
241     const struct proc_ns_operations *ops;
242     struct task_struct *tsk = current; 获得当前进程描述结构体
243     struct nsproxy *new_nsproxy;
// 创建一个新的命名空间的调用
258     new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs);
//proc目录下信息注册
264     err = ops->install(new_nsproxy, ei->ns);
//将新创建的命名空间new_nsproxy赋值给当前进程,即替换掉以前的命名空间。
269     switch_task_namespaces(tsk, new_nsproxy);
273 }

258调用的函数依然在nsproxy.c文件,该函数定义见59行。

59 static struct nsproxy *create_new_namespaces(unsigned long flags,
 60     struct task_struct *tsk, struct user_namespace *user_ns,
 61     struct fs_struct *new_fs)
 62 {
 63     struct nsproxy *new_nsp;
 64     int err;
//从nsproxy_cachep中申请一个nsproxy缓存,并将引用计数置1,
 66     new_nsp = create_nsproxy();
/mnt命名空间
70     new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, user_ns, new_fs);
//uts命名空间
 76     new_nsp->uts_ns = copy_utsname(flags, user_ns, tsk->nsproxy->uts_ns);
//ipc命名空间
 82     new_nsp->ipc_ns = copy_ipcs(flags, user_ns, tsk->nsproxy->ipc_ns);
//ns命名空间
 88     new_nsp->pid_ns = copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns);
//网络命名空间
94     new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns);
117 }

类似图13.1.1中进程3那样需要部分复制命名空间时(clone系统调用),copy_namespaces()将被调用。

123 int copy_namespaces(unsigned long flags, struct task_struct *tsk)
124 {
125     struct nsproxy *old_ns = tsk->nsproxy; //当前进程命名空间
126     struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
127     struct nsproxy *new_ns;
128     int err = 0;
129 
130     if (!old_ns)
131         return 0;
//引用计数原子加1
133     get_nsproxy(old_ns);
//复制标志
135     if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
136                 CLONE_NEWPID | CLONE_NEWNET)))
137         return 0;
//权能
139     if (!ns_capable(user_ns, CAP_SYS_ADMIN)) {
140         err = -EPERM;
141         goto out;
142     }
143 
//在复制ipc空间时,存在不同命名空间信号量的问题,切换到新的命名空间意味着原来的信号量将不可达,undolist(未处理
//信号的链表必须和新的ipc空间分离),如果标志设置有CLONE_SYSVSEM,意味着要求信号量共享,那就意味着不能创
//建新的ipc空间了。
151     if ((flags & CLONE_NEWIPC) && (flags & CLONE_SYSVSEM)) {
152         err = -EINVAL;
153         goto out;
154     }
//创建命名空间
156     new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs);
157     if (IS_ERR(new_ns)) {
158         err = PTR_ERR(new_ns);
159         goto out;
160     }
//将进程的命名空间空间指针指向新的命名空间
162     tsk->nsproxy = new_ns;
163 
164 out:
165     put_nsproxy(old_ns);
166     return err;
167 }

13.2 网络命名空间管理

网络命名空间操作主要在net/core/net_namespace.c,接13.1节的copy_net_ns()函数。该函数返回值是一个网络空间。创建网络命名空间时以创建网络命名空间进程的nsproxy-> net_ns为网络命名空间的原型,这是因为不同的网络命名空间很多的基础设施是一样的,比如对loopback回环接口的支持、TCP的支持、UDP支持、IP支持等等。

238 struct net *copy_net_ns(unsigned long flags,
239             struct user_namespace *user_ns, struct net *old_net)
240 {
241     struct net *net;
242     int rv;
//如果flag中CLONE_NEWNET没有设置,说明不需要创建新的网络命名空间,直接返回原来的命名空间。否则创建新的网
//络命名空间
244     if (!(flags & CLONE_NEWNET))
245         return get_net(old_net);
//从net_cachep为新的网络命名空间申请内存。
247     net = net_alloc();
//增加user命名空间的引用计数 
251     get_user_ns(user_ns);
252 
253     mutex_lock(&net_mutex);
//调用pernet_list上注册的服务函数,对这个新的网络命名空间执行init。
254     rv = setup_net(net, user_ns);
255     if (rv == 0) {
256         rtnl_lock();
257         list_add_tail_rcu(&net->list, &net_namespace_list); // net_namespace_list为所有命名空间串接的链表。
258         rtnl_unlock();
259     }
260     mutex_unlock(&net_mutex);
261     if (rv < 0) { //出错处理
//user命名空间计数值减一
262         put_user_ns(user_ns);
//释放net命名空间。
263         net_drop_ns(net);
264         return ERR_PTR(rv);
265     }
266     return net;
267 }

254行的setup_net()如下, 其主要工作就是遍历pernet_list获得对应的structpernet_operations结构体,然后将struct pernet_operations结构对应的实例的init成员函数作用于新创建的命名空间。

150 static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
151 {
166     list_for_each_entry(ops, &pernet_list, list) {
167         error = ops_init(ops, net);
168         if (error < 0)
169             goto out_undo;
170     }
189 }

structpernet_operations的实例还是很多的,以下截图展示了其中的一部分,对于arp.c文件,其arp_net_ops的arp_net_init()实例会在167行被调用,以初始化新网络命名空间arp协议在proc目录的接口。


图13.2.1 structpernet_operations实例

其它网络命名空间的函数如下:

get_net_ns_by_fd()根据文件描述获得网络命名空间

get_net_ns_by_pid()根据进程ID获得网络命名空间。

net_ns_init()网络命名空间初始化,pure_initcall声明,在系统启动时会被调用初始化网络命名空间。

register_pernet_subsys()注册图13.2.1中的各种操作集,调用register_pernet_operations(),完成,实质工作在__register_pernet_operations()函数中完成真正的注册。

unregister_pernet_subsys注销


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第十三章 网络命名空间(内核源码实现)--基于Linux3.10 的相关文章

  • 选择fasta文件中氨基酸超过300个且“C”出现至少4次的序列

    我有一个包含蛋白质序列的 fasta 文件 我想选择超过 300 个氨基酸且半胱氨酸 C 氨基酸出现超过 4 次的序列 我使用此命令来选择具有超过 300 个 aa 的序列 cat 72hDOWN fasta fasta bioawk c
  • 我想在 Red Hat Linux 服务器中执行 .ps1 powershell 脚本

    我有一个在窗口中执行的 ps1 powershell 脚本 但我的整个数据都在 Linux 服务器中 有什么可能的方法可以让我在红帽服务器中执行 powershell 脚本 powershell脚本是 Clear Host path D D
  • 任何退出 bash 脚本但不退出终端的方法

    当我使用exitshell 脚本中的命令 该脚本将终止终端 提示符 有什么方法可以终止脚本然后停留在终端中吗 我的剧本run sh预计通过直接获取或从另一个脚本获取来执行 编辑 更具体地说 有两个脚本run2 sh as run sh ec
  • 在本地主机上使用相同的 IP 和端口创建套接字

    我在 Linux 上看到奇怪的行为 我看到远程端和本地端都显示相同的 IP 和端口组合 以下是 netstat 输出 netstat anp 网络统计grep 6102 tcp 0 0 139 185 44 123 61020 0 0 0
  • 在ubuntu中打开spyder

    我想在ubuntu中打开spyder Python IDE 通常我会在 shell 中编写 spyder 它会打开spyder IDE 现在 当我在shell中编写spyder时 它只是换行 什么也没有发生 类似于按 enter 我如何找回
  • Python glob,操作系统,相对路径,将文件名放入列表中[重复]

    这个问题在这里已经有答案了 我正在尝试创建一个目录中所有文件的列表 其中文件名以 root 结尾 在阅读了论坛中的一些文章后 我尝试使用 glob 和 os listdir 的基本策略 但我都遇到了麻烦 首先 当我使用 import glo
  • Ruby:在 Ubuntu 上安装 rmagick

    我正在尝试在 Ubuntu 10 04 上安装 RMagick 看起来here https stackoverflow com questions 1482823 is there an easy way to install rmagic
  • 为什么此 NASM 代码会打印我的环境变量?

    本学期我刚刚完成计算机体系结构课程 除其他外 我们一直在涉足 MIPS 汇编并在 MARS 模拟器中运行它 今天 出于好奇 我开始在我的 Ubuntu 机器上摆弄 NASM 基本上只是将教程中的内容拼凑起来 并感受一下 NASM 与 MIP
  • Crontab 每 5 分钟一次 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我如何告诉 crontab 每 5 分钟运行一次 但从每小时的第二分钟开始 换句话说 我想在以下时间执行我的脚本minute 5 2 例如 我的脚本应
  • /sys/device/ 和 dmidecode 报告的不同 CPU 缓存大小

    我正在尝试获取系统中不同缓存级别的大小 我尝试了两种技术 a 使用 sys device 中的信息 这是输出 cat sys devices system cpu cpu0 cache index1 size 32K cat sys dev
  • 为什么 fork 炸弹没有使 android 崩溃?

    这是最简单的叉子炸弹 我在许多 Linux 发行版上执行了它 但它们都崩溃了 但是当我在 android 终端中执行此操作时 即使授予后也没有效果超级用户权限 有什么解释为什么它没有使 Android 系统崩溃吗 一句话 ulimit Li
  • 如何在不使用 IDE 的情况下在 Linux 上运行 Java 项目

    我是 Java 新手 基本上 我开发了一个java项目 其中包含Eclipse中的多个Java包 该项目在我安装了 redhat Linux 的桌面上运行正常 然而 我需要在一个更强大的没有安装X11的Linux服务器 redhat ent
  • Tomcat Intellij Idea:远程部署

    RackSpace 云服务器 Ubuntu 12 04 Intellij Idea 11 1 2 Windows 8 Tomcat 7 0 26 JDK 6 在 Intellij Idea 上 当我尝试在远程 Tomcat 7 服务器上运行
  • vmsplice() 和 TCP

    在原来的vmsplice 执行 有人建议 http lwn net Articles 181169 如果您的用户态缓冲区是管道中可容纳的最大页面数的 2 倍 则缓冲区后半部分成功的 vmsplice 将保证内核使用缓冲区的前半部分完成 但事
  • 仅使用containerd(不使用Docker)修剪容器镜像

    如果我刚刚containerd安装在 Linux 系统上 即 Docker 是not安装 如何删除未使用的容器映像以节省磁盘空间 Docker 就是这么方便docker system prune https docs docker com
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • ALSA:snd_pcm_writei 调用时缓冲区不足

    当运行我最近从灰烬中带回来的旧程序时 我遇到了缓冲区不足的情况 该程序将原始声音文件完全加载到内存中 2100 字节长 525 帧 并准备 ALSA 进行输出 44 1khz 2 通道 有符号 16 位 if err snd pcm set
  • 适用于 Linux 的轻量级 IDE [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 C 中使用单个消息队列是否可以实现双向通信

    我希望服务器向客户端发送一些消息 并让客户端确认它 我被分配了这个任务 我可以在 C linux 中使用单个消息队列来完成它还是我需要创建两个 谢谢 是的 可以使用 sysV 消息队列来做到这一点 从您之前的问题来看 您正在使用该队列 您可
  • 如何为 Linux 桌面条目文件指定带有相对路径的图标?

    对于我的一个 Linux 应用程序 我有应用程序二进制文件 一个 launcher sh 脚本 针对 LD LIBRARY PATH 和一个 desktop 文件 所有这些都位于同一文件夹中 我想使用图标的相对路径而不是绝对路径 我试过了

随机推荐

  • Window10运行Docker踩过的坑

    Window10运行Docker踩过的坑 摘要 1 Docker for Windows 仅支持专业版 2 docker machine启动docker时 docker里的文件没了 3 docker安装Redis时配置文件出错 最近新装系统
  • Qt: QPushButton 常用样式设置(qss)

    1 设置上边框为2个像素 样式为实线 颜色为黑色 border top 2px solid 000000 2 设置上内边距为 8px 文字向下移动 padding top 8px 3 给文字加下划线 text decoration unde
  • visual studio 2019中文乱码

    文章目录 1 编码 1 code编码 2 控制台编码 3 txt文件编码 4 控制台编码 2 中文输出 1 更改 locale 显示中文 1 cout 与 wcout 2 ofstream 与 wofstream 3 printf 和 wp
  • java switch-case练习 常见题型

    一 使用 switch 把小写类型的 char型转为大写 只转换 a b c d e 其它的输 出 other 提示 String word scan next char c word charAt 0 switch c public cl
  • sqlalchemy Connection Pool

    sqlalchemy 默認的pool size 5 pool裡存放的是在跟數據庫的的閒置連接 使用c1 engine connect 或 session scoped session sessionmaker bind engine 會創建
  • AI数字人:语音驱动面部模型及超分辨率重建Wav2Lip-HD

    1 Wav2Lip HD项目介绍 数字人打造中语音驱动人脸和超分辨率重建两种必备的模型 它们被用于实现数字人的语音和图像方面的功能 通过Wav2Lip HD项目可以快速使用这两种模型 完成高清数字人形象的打造 项目代码地址 github地址
  • 判断服务器芯片还是民用芯片,抢鲜看,Xeon E3-1230对比I7 2600评测

    印在包装上的规格 附带的原装风扇与桌面级完全相同 CPU正反面对比图 除了型号之外完全相同 在研究完CPU之后还有必要研究一下所支持的主板芯片组 Intel方面给予Xeon E3 1000系列所提供的芯片组分为C202 C204以及C206
  • 使用 RedisTemplate 对象的 opsForValue() 方法获取 Redis 中的值获取不到

    问题 使用 RedisTemplate 对象的 opsForValue 方法获取 Redis 中的值获取不到 详细问题 笔者代码如下 1 使用 ValueOperations 对象的 set 方法将一个键值对存储到 Redis 中 valu
  • 75-局部自定义指令——bind和update方法

    75 局部自定义指令 bind和update方法 这里通过directives指令实现
  • OPENWRT或旁路由如果不能正常使用opkg,正确上网等的一种解决方法

    家里有个n1 我刷了个openwrt做旁路由 主路由是 AC2100 莫名其妙的无法正常使用某些功能 例如opkg updae 正确上网也不行 按照之前的教训 防火墙的设置影响较大 我用的防火墙规则是自带的lan规则 如下图所示 并不满足作
  • win11安装tensorRt成功

    1 安装cuda 查看电脑cuda版本 nvidia smi 我的是11 6 下载链接 https developer nvidia com cuda 11 6 0 download archive target os Windows ta
  • 《域渗透攻防指南》签名版预售来啦

    千呼万唤始出来 终于 在广大粉丝翘首期盼下 国内首本专门讲述域内攻防的书籍 域渗透攻防指南 在2022年最后一个月和大家见面了 为了回馈粉丝的等待 让粉丝早日拿到心仪的书 特此联合机械工业出版社弄了签名版书预售活动 数量有限 仅限前500名
  • Typescript - 枚举类型 enum,详细介绍与使用教程(快速入门)

    介绍 在任何项目开发中 我们都会遇到定义常量的情况 常量就是指不会被改变的值 TS 中我们使用 const 来声明常量 但是有些取值是在一定范围内的一系列常量 比如一周有七天 比如方向分为上下左右四个方向 这时就可以使用枚举 Enum 来定
  • JavaScript-三种弹窗方式

    JavaScript 三种弹窗方式 一 alert 带内容的弹框 用法 二 confirm 带选择的弹框 用法 专门建立的学习Q q u n 731771211 分享学习方法和需要注意的小细节 不停更新最新的教程和学习技巧 从零基础开始
  • 如何在mac上运行vue项目

    本人使用的是Mac笔记本 所以搭建Vue环境的时候遇到了一些坑 在此做下记录希望可以帮到和我一样掉坑的人 都说Vue和小程序有些地方很相似 便从朋友手里要了一个Vue的项目想着尝试看看 结果项目到手才发现坑了不是一个编辑器运行就可以解决的
  • LeetCode 236. 二叉树的最近公共祖先——Python实现(递归,哈希表)

    1 直接用递归的方法 使用递归的方法 找出二叉树中两个节点的最近公共祖先 分析如下 对于两个节点p和q的公共祖先r 他们要么在r的同一边 要么在这个节点的两边 因此 只要满足这两个条件即可 也就是说 只要 f r child p and f
  • 【光伏功率预测】基于EMD-PCA-LSTM的光伏功率预测模型(Matlab代码实现)

    个人主页 研学社的博客 欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 文献来源 4 Matlab代码 数据 文章讲解 1 概述 文献来
  • slam数据集整合

    根据大家的要求 在此整合一下常用的几个数据集 我平时话太啰嗦了 这里就简单一些 为啥编辑器的分隔线都这么萌 1 Tum数据集 这个大家用的人都知道 RGB D数据集 有很多个sequence 自带Ground truth轨迹与测量误差的脚本
  • 【ElasticSearch】ElasticSearch 中使用衰减函数来完美你的搜索结果

    1 概述 转载 ElasticSearch 中使用衰减函数来完美你的搜索结果 最近的项目在原有的搜索需求增加功能 ElasticSearch 7 6 请注意 大版本不同可能参数不同 原有搜索 简单的标题 正文 全文索引 新加功能 在原有的基
  • 第十三章 网络命名空间(内核源码实现)--基于Linux3.10

    下载地址 http download csdn net detail shichaog 8620701 有两篇翻译博文 Lxc之二 网络设置 和 linuxnamespace 之使用 LXC文章中关于网络的设置是从用户空间配置的 从该文章可