linux代码之namespace

/*
 * 2020/12/15    11:58    yin
 *
 * namespace 是 linux 内核提供的特性,为虚拟化而生
 */


/*
 * nsproxy
 */

struct nsproxy {
    atomic_t count;
    struct uts_namespace *uts_ns;
    struct ipc_namespace *ipc_ns;
    struct mnt_namespace *mnt_ns;
    struct pid_namespace *pid_ns_for_children;
    struct net          *net_ns;
    struct cgroup_namespace *cgroup_ns;
};
extern struct nsproxy init_nsproxy;


/*
 * namespace
 */

    机制提供了一种资源隔离的解决方案

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

    cat /proc/[pid]/ns

    目前Linux内核里面实现且支持的Namespace有7种

    名称            定义                说明

    Cgroup        CLONE_NEWCGROUP            Cgroup root directory ( Linux 4.6)

    IPC            CLONE_NEWIPC            隔离进程间通信 ( Linux 2.6.19)

    Network        CLONE_NEWNET            隔离网络资源 ( Linux 2.6.24)

    Mount        CLONE_NEWNS                隔离文件系统挂载点 ( Linux 2.4.19)

    PID            CLONE_NEWPID            隔离进程的ID ( Linux 2.6.24)

    User        CLONE_NEWUSER            隔离用户和用户组的ID (started in Linux 2.6.23 and completed in Linux 3.8)

    UTS            CLONE_NEWUTS            (UNIX Time-sharing System) namespace提供了主机名和域名的隔离
                                        能够使得子进程有独立的主机名和域名(hostname),这一特性在Docker容器技术中被用到,
                                        使得docker容器在网络上被视作一个独立的节点,而不仅仅是宿主机上的一个进程。

/*
 * PID Namespace
 */
    在 Linux 系统中创建进程的系统调用是 clone()

    int pid = clone(main_function, stack_size, SIGCHLD, NULL);

    这个系统调用就会为我们创建一个新的进程,并且返回它的进程号 pid。

    我们用 clone() 系统调用创建一个新进程时,就可以在参数中指定 CLONE_NEWPID 参数,比如:

    int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);

    这时,新创建的这个进程将会“看到”一个全新的进程空间,在这个进程空间里,它的 PID 是 1。


/*
 * Docker
 */
    Docker中利用UTS namespace原理,每个镜像可以以本身所提供的服务名称来命名镜像的hostname,且不会对宿主机产生任何影响,
    由此达到主机名和域名的隔离效果。

    namespace 是 linux 内核提供的特性,为虚拟化而生。随着 docker 的诞生引爆了容器技术,也把长期在后台默默奉献的 namespace 技术推到了大家的面前。


/*
 * UTS Namespace
 */

    UTS Namespace提供了主机名和域名的隔离,也就是struct utsname里的nodename和domainname两个字段。不同Namespace中可以拥有独立的主机名和域名。

    那么为什么需要对主机名和域名进行隔离呢?因为主机名和域名可以用来代替IP地址,如果没有这一层隔离,同一主机上不同的容器的网络访问就可能出问题。


/*
 * IPC Namespace
 */
    IPC Namespace是对进程间通信的隔离,进程间通信常见的方法有信号量、消息队列和共享内存。
    
    IPC Namespace主要针对的是SystemV IPC和Posix消息队列,这些IPC机制都会用到标识符,比如用标识符来区分不同的消息队列,

    IPC Namespace要达到的目标是相同的标识符在不同的Namepspace中代表不同的通信介质(比如信号量、消息队列和共享内存)。


/*
 * API
 */
    /* 创建一个新的进程并把他放到新的namespace中 */
    int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg);

    /* 将当前进程加放到已有的namespace中 */
    int setns(int fd, int nstype);

    /* 使当前进程退出指定类型的namespace,并加入到新创建的namespace(相当于创建并加入新的namespace) */
    int unshare(int flags);

    /* clone 和 unshare 区别 */
    两者都是创建并加放新的namespace,区别是:
    unshare 是使当前进程加入新的namespace
    clone 是创建一个新的子进程,然后让子进程加入新的namespace,而当前进程保持不变
        

猜你喜欢

转载自blog.csdn.net/xiaozhiwise/article/details/111213620
今日推荐