Docker技术内幕3——Namespace的接口和使用

目前Linux内核总共实现了6种Namespace。

IPC:隔离System V IPC 和 POSIX消息队列

Network:隔离网络资源

Mount:隔离文件系统挂载点

PID:隔离进程ID

UTS:隔离主机名和域名

User:隔离用户ID和组ID。


对Namespace的操作,主要是通过clone、setns、unshare这三个系统调用来完成的。

clone可以用来创建新的Namespace。

每个进程在procfs下都有一个ns目录,用来存放namespace相关的信息。

Docker技术内幕3——Namespace的接口和使用_第1张图片

创建一个新的命名空间:clone():

创建一个命名空间的方法是使用clone系统调用,其会创建一个新的进程。函数原型如下:

int clone(int (*child_func)(void *),void * child_stack,int flags,void * arg);

举个例子:

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define errExit(msg) do{perror(msg);exit(EXIT_FAILURE);}while(0)
#define STACK_SIZE (1024*1024)

static int childFunc(void *arg){

    struct utsname uts;
    if(sethostname(arg,strlen(arg))==-1){
      errExit("set hostname");
   }

   if(uname(&uts)==-1){

     errExit("uname");
   }

   printf("uts.nodename in child:%s\n",uts.nodename);
   sleep(100);
   return 0;

}


static char child_stack[STACK_SIZE];


int main(int argc,char * argv[]){

pid_t child_pid;
struct utsname uts;
if(argc<2){

 fprintf(stderr,"Usage:%s\n",argv[0]);
 exit(EXIT_FAILURE);

}

child_pid=clone(childFunc,child_stack+STACK_SIZE,CLONE_NEWUTS|SIGCHLD,argv[1]);

sleep(1);

if(uname(&uts)==-1){

 errExit("uname");

}

printf("uts.nodename in parent:%s\n",uts.nodename);

if(waitpid(child_pid,NULL,0)==-1){

  errExit("waitpid");
}

printf("child has terminated\n");
exit(EXIT_SUCCESS);


return 0;

}

Docker技术内幕3——Namespace的接口和使用_第2张图片


关联一个存在的命名空间:setns():

sentns的 函数原型如下:

int setns(int fd,int nstype);

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 

#define errExit(msg) do{perror(msg);exit(EXIT_FAILURE);}while(0)

int main(int argc,char *argv[]){

int fd;
if(argc<3){

 fprintf(stderr,"%s /proc/PID/ns/FILE cmd [arg...]\n",argv[0]);
 exit(EXIT_FAILURE);

}

fd=open(argv[1],O_RDONLY);
if(fd==-1){
  errExit("open");
}
if(setns(fd,0)==-1){
  errExit("setns");
}

execvp(argv[2],&argv[2]);
errExit("execvp");


}

使当前进程退出指定的Namespace,并加入到新创建的Namespace:unshare

跟clone类似,不同之处是unshare是使当前进程加入到namespace,clone是创建一新的子进程,然后让进程加入新的namespace,而当前进程保存不变。

unshare()系统调用的函数原型如下:

int unshare(int flags);

你可能感兴趣的:(Docker与云安全,C/C++)