zoukankan      html  css  js  c++  java
  • Docker原理之Namespace

     Linux Namespace

      namespace是linux内核用来隔离内核资源的方案。 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前 namespace 里的进程,对其他 namespace 中的进程没有影响。

    隔离资源

    名称 宏定义   隔离的资源
    IPC  CLONE_NEWIPC System V IPC(信号量、消息队列、共享内存) 和POSIX MESSAGE QUEUES
    Network CLONE_NEWNET Network devices、stacks、ports(网络设备、网络栈、端口等)
    Mount  CLONE_NEWNS Mount points(文件系统挂载点)
    PID CLONE_NEWPID Process IDs(进程编号)
    User CLONE_NEWUSER User and Groups IDs(用户和用户组)
    UTS CLONE_NEWUTS Hostname and NIS domain name(主机名与NIS域名)
    Cgroup CLONE_NEWCGROUP Cgroup root directory(cgroup的根目录)

    表现形式

    • 查看进程ID的namespace  
    # 查看进程18863的namespace
    ll /proc/18863/ns

      

       可以看到,namespace 是链接文件,格式为[隔离类型:唯一标识],唯一标识可看成namespace的ID,同一个ID下的进程共享该namespace的全局资源。

    函数

    • clone():Clone()函数是在libc库中定义的一个封装函数,它负责建立新轻量级进程的堆栈并且调用对编程者隐藏了clone系统条用。实现clone()系统调用的sys_clone()服务例程并没有fn和arg参数。封装函数把fn指针存放在子进程堆栈的每个位置处,该位置就是该封装函数本身返回地址存放的位置。Arg指针正好存放在子进程堆栈中的fn的下面。当封装函数结束时,CPU从堆栈中取出返回地址,然后执行fn(arg)函数。
    • setns(): 通过 setns() 函数可以将当前进程加入到已有的 namespace 中。
    • unshare():通过 unshare 函数可以在原进程上进行 namespace 隔离。

    容器里的进程看到的文件系统

      启用隔离函数CLONE_NEWNS, 进入容器看到就是容器自己的文件系统?

    • 函数验证, 在~目录下创建个ns.c文件
    #define _GNU_SOURCE
    #include <sys/mount.h> 
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdio.h>
    #include <sched.h>
    #include <signal.h>
    #include <unistd.h>
    #define STACK_SIZE (1024 * 1024)
    static char container_stack[STACK_SIZE];
    char* const container_args[] = {
      "/bin/bash",
      NULL
    };
    
    int container_main(void* arg)
    {  
      printf("进入容器里面!
    ");
    execv(container_args[0], container_args); printf("错误 ");
    return 1; } int main() { printf("宿主机启动一个容器! ");
    int container_pid = clone(container_main, container_stack+STACK_SIZE, CLONE_NEWNS | SIGCHLD , NULL); waitpid(container_pid, NULL, 0); printf("容器停止! ");
    return 0; }

      编译并执行:

    # 编译
    gcc -o  ns ns.c -D_GNU_SOURCE  -lpthread
    # 执行
    ./ns

      结果:

      

      执行ns,显示我们进入到了一个容器中。假象我们容器是挂载到/tmp目录下,查看/tmp,其实这里仍然是宿主机的文件。紧接着,把容器以 tmpfs(内存盘)格式,重新挂载了 /tmp 目录。

    #define SOURCE
    #include <sys/mount.h> 
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdio.h>
    #include <sched.h>
    #include <signal.h>
    #include <unistd.h>
    #define STACK_SIZE (1024 * 1024)
    static char container_stack[STACK_SIZE];
    char* const container_args[] = {
      "/bin/bash",
      NULL
    };
    
    int container_main(void* arg)
    {  
      printf("进入容器里面!
    ");
     
      mount("none", "/tmp", "tmpfs", 0, "");
    
      execv(container_args[0], container_args);
    
      printf("错误
    ");
      return 1;
    }
    
    int main()
    {
      printf("宿主机启动一个容器!
    ");
      int container_pid = clone(container_main, container_stack+STACK_SIZE, CLONE_NEWNS | SIGCHLD , NULL);
      waitpid(container_pid, NULL, 0);
      printf("容器停止!
    ");
      return 0;
    }

       在容器启动前加 mount("none", "/tmp", "tmpfs", 0, "");

       再编译执行ns,挂载后,就看不见任何宿主机的文件了。这就是在当前容器下的单独的文件系统了。

       

    参考

      https://time.geekbang.org/column/article/17921

      本文直接拷贝了部分代码,如有侵权,请告知删除。

    目录

      https://www.cnblogs.com/lioa/p/12664686.html

  • 相关阅读:
    学习素材、网站
    用 Python脚本生成 Android SALT 扰码
    H面试程序(29):求最大递增数
    常用数据库查询判断表和字段是否存在
    《火球——UML大战需求分析》(第3章 分析业务模型-类图)——3.7 关于对象图
    N个数依次入栈,出栈顺序有多少种
    WIN ERROR:C:WindowsSystem32<LANG_NAME>mstsc.exe.MUI
    大端法和小端法
    freopen()重定向的打开和关闭
    Linux 的 Spinlock 在 MIPS 多核处理器中的设计与实现
  • 原文地址:https://www.cnblogs.com/lioa/p/12666497.html
Copyright © 2011-2022 走看看