我正在使用以下C函数从 单个流程实例* 创建 多个网络名称空间 : *
void create_namespace(const char *ns_name) { char ns_path[100]; snprintf(ns_path, 100, "%s/%s", "/var/run/netns", ns_name); close(open(ns_path, O_RDONLY|O_CREAT|O_EXCL, 0)); unshare(CLONE_NEWNET); mount("/proc/self/ns/net", ns_path, "none", MS_BIND , NULL); }
在我的过程创建了所有命名空间之后,我向一个网络名称空间中的任何一个添加了 tap 接口(使用ip link set tap1 netns ns1命令),然后我实际上在所有名称空间中看到了该接口(大概这实际上是一个使用不同名称的单个名称空间) )。
ip link set tap1 netns ns1
但是,如果我通过使用多个进程创建多个名称空间,那么一切工作都很好。
这有什么问题吗?我是否必须传递任何其他标志到unshare()才能从单个流程实例开始工作?是否存在单个流程实例不能创建多个网络名称空间的限制?还是mount()因为/proc/self/ns/net实际安装多次而导致通话出现问题?
unshare()
mount()
/proc/self/ns/net
更新: 似乎该unshare()函数正确创建了多个网络名称空间,但/var/run/netns/实际上所有安装点都引用该目录中已安装的第一个网络名称空间。
/var/run/netns/
Update2: 似乎最好的方法是对另一个进程进行fork()并从那里执行create_namespace()函数。无论如何,我将很高兴听到一个更好的解决方案,该解决方案不涉及fork()调用,或者至少得到一个确认,该确认将证明不可能从单个进程创建和管理多个网络名称空间。
Update3: 通过使用以下代码,我可以使用unshare()创建多个名称空间:
int main() { create_namespace("a"); system("ip tuntap add mode tap tapa"); system("ifconfig -a");//shows lo and tapA interface create_namespace("b"); system("ip tuntap add mode tap tapb"); system("ifconfig -a");//show lo and tapB interface, but does not show tapA. So this is second namespace created. }
但是在进程终止并执行后ip netns exec a ifconfig -a,ip netns exec b ifconfig -a似乎两个命令都突然在命名空间 a中 执行 了 。因此,实际的问题是存储对名称空间的引用(或以正确的方式调用mount()。但是我不确定,如果可以的话)。
ip netns exec a ifconfig -a
ip netns exec b ifconfig -a
仅/proc/*/ns/*当您需要从另一个进程访问这些名称空间,或者需要获取能够在两者之间来回切换的句柄时,才需要绑定mount 。不需要在单个进程中使用多个名称空间。
/proc/*/ns/*
每当您执行open(/proc/N/ns/net)时,它都会为此文件创建inode,所有后续open()都将返回绑定到相同名称空间的文件。内核dentry缓存的深度丢失了详细信息。
/proc/N/ns/net
同样,每个进程只有一个/proc/self/ns/net文件条目,并且绑定安装不会创建此proc文件的新实例。打开这些已挂载的文件 与/proc/self/ns/net直接打开 文件 完全相同 (它将始终指向您首次打开文件时指向的名称空间)。
似乎/proc/*/ns像这样“半生不熟”。
/proc/*/ns
因此,如果仅需要2个名称空间,则可以:
/proc/1/ns/net
并在两者之间切换。
可能需要多于2个clone()。/proc/N/ns/net每个进程似乎无法创建多个文件。
clone()
但是,如果您不需要在运行时在名称空间之间切换,也不需要与其他进程共享它们,则可以使用许多这样的名称空间:
打开的套接字会引用其网络名称空间,因此只有在套接字关闭后才能收集它们。
您还可以使用netlink通过在源名称空间上发送netlink命令,并通过PID或名称空间FD(您没有后者)来指定dst名称空间,从而在名称空间之间移动接口。
您需要在访问/proc依赖于该名称空间的条目之前切换进程名称空间。打开“ proc”文件后,它将继续引用命名空间。
/proc