runC nsexec.c 解析

一直以为runc中也用clone 函数加参数形式实现进程命名空间隔离,但是细读runc中命名空间隔离的实现文件nsexec.c 发现并没有简单实用clone实现。而是因为selinux问题,内核版本等问题,并没有简单使用clone实现,而是配合其他namespace API实现
Namespace API提供了三种系统调用接口:
  ● clone():创建新的进程
  ● setns():允许指定进程加入特定的namespace
  ● unshare():将指定进程移除指定的namespace
nsexec.c分别使用这三种接口,对于一般新建命名空间,使用unshare()实现;对于已有的命名空间,使用setns()实现。


runc 通过nsexec.c 提供setns来设置命名空间,以避免go 语言多线程问题(没搞懂)。


nsexec.c 里面的nsexec()函数在包被导入时候就开始执行,等待通过管道传输ns数据过来
nsexec()首先通过环境变量_LIBCONTAINER_INITPIPE 获取初始管道的的文件描述符。该管道是父进程打开并保持打开状态,跨越初始进程和nsenec clone出来的进程。
如下图是nsexec.c 流程图:
关键是unshare(config.cloneflags),改config.cloneflags默认值值是(CLONE_NEWNET|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWUTS|CLONE_NEWNS) 唯独没有CLONE_NEWUSER。

然后这个unshare出来的命名空间在改进程child clone出来的init 进程体现出来,init 进程查看自己的pid:1 ,ppid:0.

runC nsexec.c 解析