我正在使用以下 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
命令)之后,我实际上在所有命名空间中都看到了这个接口(大概,这实际上是一个使用不同名称的单个命名空间)。
但是,如果我使用多个进程创建多个命名空间,那么一切正常。
这里有什么问题?我是否必须将任何其他标志传递unshare()
给 才能从单个流程实例中工作?是否存在单个流程实例不能创建多个网络命名空间的限制?还是调用有问题mount()
,因为/proc/self/ns/net
实际挂载了多次?
更新:
似乎该unshare()
函数正确地创建了多个网络命名空间,但/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()。但我不确定这是否可能)。