1. 一个新的namesapce
Introduction
实际上那些我们常见的东西, 比如挂载点, POSIX消息队列, pid空间等等都是在一个指定的命名空间下的, 换句话说如果我们有两个命名空间, 那么你的电脑上能出现两个相同pid的进程, 神奇.
$ docker run -it ubuntu:latest bash
$ ps -aux
你会发现你的 pid=1
的进程就是bash, 我电脑上的一号进程是bash吗? 这是因为docker帮你创建了一个新的 pid namesapce
, 在两个不同的namespace下自然是可以做到pid重叠的, 就好像在c++不同的namespace下能出现两个同名变量一样
除了能帮你隔离pid, Linux上还有一大堆别的命名空间:
ipc namespace : 隔离进程间通信
mount namespace: 隔离挂载点
network namespace[今天的重点] : 隔离网络资源
搞个命名空间玩玩
ok 开始我们的Linux网络之旅, 我们按照顺序执行以下的内容:
ip netns add xiaohan
创建一个nns, 创建完成以后执行ip netns list
, 来看看自己现在除了默认nns以外还有那些命名空间, 会发现多了一个名为xiaohan的nns. 然后好玩的就开始了, 我们现在有了一个nns了, 走进去玩嘿嘿
ip netns exec xiaohan bash
现在我们就进入了名为xiaohan的命名空间了, 整点啥好呢?
# 强的, 只有一个loop设备, 状态害是DOWN呢, loop设备DOWN了会怎样?
$ ip link list # 检查网络设备
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN
# 太强了, 这世界上有人ping自己都ping不通, 果然是强者的世界
$ ping localhost
connect: Network is unreachable
# 给我起!
$ ip link set dev lo up
# 可以了嘿嘿
$ ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.014 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.032 ms
搞个veth玩一玩
我们就先玩一玩, 关于veth的详细使用下一节说, 反正你现在只要知道veth是成对出现的, 类似于电话一样, 一头讲一头听的, 我们先玩一把
$ ip link add veth0 \ # 创建一个名为veth0的设备
type veth \ # 类型为veth设备
peer name veth1 # 对端名称为veth1
$ ip link set veth1 \ # 设置一下veth1这一头
netns xiaohan # 放到xiaohan的命名空间里
现在爽了, 我们给[默认]命名空间 & [xiaohan]命名空间, 拉了一条网线, 然后给他俩一人一个IP, 那么两个命名空间内就可以相互聊天了!
$ ifconfig veth0 10.1.1.1/24 up # veth0 一个IP
$ ip netns exec xiaohan bash # 然后进入命名空间
$ ifconfig veth1 10.1.1.2/24 up # veth1 也一个IP
$ ping 10.1.1.2 # 两个veth开始聊天...
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.022 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.030 ms
API - 创建一个进程+ns
int clone(
void* child_func,
void* child_stack,
void* child_args,
int flags,
)
进入一种严肃的玩法, 以上的函数ok帮你创建一个新的进程, 创建一个(新进程+新空间)的组合, 创建出来的新进程就在这个新进程里面. 当然这些并不是重点, 重点是这些参数太熟悉了...
回忆一下我们在Go语言里面如何创建出一个新g? 我们切换到g0栈上, 分配栈, 将函数执行指针拷贝, 然后将函数参数拷贝到栈内. 换句话说对待任何人, 想要执行一个"任务", 都必须提供函数执行体 + 参数 + 栈 . 我们创建进程是这么做, Go创建协程也这么做 因此你可以这么说: "任务" = "函数+参数+栈"
API - 往ns里丢一个进程
int setns(int fd)
这个函数能负责把当前进程加入指定的命名空间下, 其中的fd就代表了命名空间. 一个常见的玩法是把当前进程换成bash, 那么就相当于切换到nns下开始执行操作, 是不是很像我们之前看到的ip netns exec xiaohan bash
, 这个操作使用API来完成就是这样的:
fd = open(xiaohan, O_RDONLY) // 打开xiaohan文件描述符
setns(fd,0) // 现在你在xiaohan下了
execvp("/bin/bash") // 本进程被替换成bash了, 玩吧
Last updated
Was this helpful?