第十三章 网络命名空间(内核源码实现)--基于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 的相关文章

  • 健全性检查 SSH 公钥? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我已要求用户提供他们的公共 id rsa pub ssh 密钥 然后将其放入 home theiraccount ssh authorized key
  • Linux 缓冲区溢出环境变量

    我一直在审查不同类型的缓冲区溢出 并遇到了一个我不记得为什么会发生的问题 下面的代码是我尝试执行缓冲区溢出的程序 include
  • 更改子进程中的 iostream

    现在 我正在开发一个项目 其中我需要启动一个子进程来使用 C 在 Linux 中执行一个新程序 并且我需要重定向标准输入和输出 就像在 C 中一样 它们是cin and cout 到一个文件 这意味着在子进程中 标准输入和输出都是文件 子进
  • 为所有图像添加前缀(递归)

    我有一个包含 5000 多张图像的文件夹 全部带有 JPG 扩展名 我想要做的就是递归地向所有图像添加 thumb 前缀 我发现了一个类似的问题 重命名文件和目录 添加前缀 https stackoverflow com questions
  • 如何在Linux中打开端口[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我已经安装了 Web 应用程序 该应用程序在 RHEL centOS 上的端口 8080 上运行 我只能通过命令行访问该机器 我尝试从我的
  • 用于列出用户和组的 Python 脚本

    我正在尝试编写一个脚本 在自己的行上输出每个用户及其组 如下所示 user1 group1 user2 group1 user3 group2 user10 group6 etc 我正在为此用 python 编写一个脚本 但想知道如何做到这
  • 使用 perf 查找线程瓶颈并优化挂机时间

    对 cpu 周期进行采样perf record如果核心利用率大致恒定 则对于寻找优化候选非常有用 但对于具有并行性不同的多个阶段的代码 计算 cpu 周期将重点强调并行阶段 而低估影响挂机时间的顺序或有限并行阶段 简而言之 天真的 perf
  • 找出某个日期时间自unix纪元以来的时间?

    我想找出 2009 年 10 月 1 日 9 00 BST 的 UNIX 时间 即自 Unix 纪元以来的秒数 我如何在 Linux 命令行上执行此操作 我知道你可以使用date UNIXTIME someformat 但是unix时间是我
  • vm.dirty_ratio 和 vm.dirty_background_ratio 之间的区别?

    我目前正在试验中找到的内核参数 proc sys vm 尤其dirty ratio and dirty background ratio 内核文档对两者都有以下解释 脏背景比例 包含 以包含空闲页面的总可用内存的百分比表示 和可回收页 后台
  • GCC 4.7 字符串文字的源字符编码和执行字符编码?

    Linux x86 64 上的 GCC 4 7 是否具有默认字符编码 用于验证和解码 C 源文件中字符串文字的内容 这是可配置的吗 此外 当将字符串数据从字符串文字链接到输出的数据部分时 它是否具有默认的执行字符编码 这是可配置的吗 在任何
  • Amazon EC2 - Apache 服务器重启问题

    当我运行这个命令时 sudo etc init d httpd restart 它给出以下错误 停止 httpd 失败 启动 httpd 98 地址已在使用中 make sock 无法绑定到地址 80 98 地址已在使用 make sock
  • 如何在 Linux 上调用 Python 中的内联机器代码?

    我正在尝试从 Linux 上的纯 Python 代码调用内联机器代码 为此 我将代码嵌入到字节文字中 code b x55 x89 xe5 x5d xc3 然后打电话mprotect http www kernel org doc man
  • 为什么分配大块内存会失败,而重新分配小块内存却不会失败

    这段代码的结果是x指向一块大小为 100GB 的内存 include
  • 使用请求和多处理时的奇怪问题

    请检查这个Python代码 usr bin env python import requests import multiprocessing from time import sleep time from requests import
  • 安全地记住 bash 脚本中的 ssh 凭据[重复]

    这个问题在这里已经有答案了 假设我有一个 bash 脚本 它通过 ssh 在远程计算机上执行命令 Do something here ssh otheruser host command1 Do something else ssh oth
  • 使用多线程的套接字服务器或文件服务器实现:概念不清楚

    请帮我理清这个概念 假设我们有一个使用线程实现的套接字端口服务器 套接字服务器侦听套接字端口 并在消息到达时创建一个线程来服务该请求 客户端代码向服务器发送给定数量的消息 该客户端代码也可以由多个用户在不同的计算机上运行 我知道客户端代码作
  • 数百个空闲线程的影响

    我正在考虑使用可能数百个线程来实现通过网络管理设备的任务 这是一个在带有 Linux 内核的 powerpc 处理器上运行的 C 应用程序 在每个任务进行同步以将数据从设备复制到任务的初始阶段之后 任务变得空闲 并且仅在收到警报或需要更改一
  • 无法在 R 中安装插入符号包(在我的 Linux 机器中)

    我在尝试在 R 中安装插入符号包时遇到以下错误 g error tmp Rtmp2Tos7n R INSTALL2e6e30153a74 nloptr nlopt 2 4 2 lib libnlopt cxx a No such file
  • MYSQL插入GB大小的巨大SQL文件

    我正在尝试创建 Wikipedia DB 副本 大约 50GB 但在处理最大的 SQL 文件时遇到问题 我使用 linux split 实用程序将 GB 大小的文件拆分为 300 MB 的块 例如 split d l 50 enwiki 2
  • 从命名管道读取

    我必须实现一个 打印服务器 我有 1 个客户端文件和 1 个服务器文件 include

随机推荐

  • 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文章中关于网络的设置是从用户空间配置的 从该文章可