精华内容
下载资源
问答
  • linux命名空间(namespace)学习(一)

    千次阅读 2018-12-05 20:42:53
    关于linux命名空间网络上有很多是关于docker 的,也有关于linux的专门的linux的namespace介绍的,没有专门介绍Linux命名空间的应用的。所以我想先介绍一下linux命名空间的应用,然后再介绍linux内核对于命名空间的...

    关于linux命名空间网络上有很多是关于docker 的,也有关于linux的专门的linux的namespace介绍的,没有专门介绍Linux命名空间的应用的。所以我想先介绍一下linux命名空间的应用,然后再介绍linux内核对于命名空间的管理方式。好了,废话不多说先上原理吧。
    命名空间在linux中是实现资源隔离的一种手段,也是轻量级虚拟化的一种手段。可以实现多个用户,也可以实现多个网络设备访问(虚拟化网络),但是实体网络却只有一个。资源隔离意味着比如不通PID命名空间看到的PID进程是不一样的,不通命名空间看到的IPC通信是不一样的。
    命名空间分类:

     1. UTS命名空间
     2.IPC命名空间;
     3.PID命名空间;
     4.文件命名空间;
     5.网络命名空间;
     6.用户命名空间;
    

    本博客会先在用户用户命名空间的使用方式上介绍前四种命名空间;
    代码如下:
    <ipc_clone.c>

    #define _GNU_SOURCE
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    #include <sched.h>
    #define STACK_SIZE (1024*1024)
    
    static char container_stack[STACK_SIZE];
    const char * args  = "/bin/bash";
    
    int contain_func(void * arg)
    {
            printf("this is in %s, and pid : %d \n", __func__, getpid());
    
            sethostname("alexander", 10);
            system("mount -t proc proc /proc");
            execv(args, arg);
            printf("this is in %s end\n", __func__);
            return 1;
    }
    
    
    int main(void)
    {
            int clone_pid = clone(contain_func, container_stack + STACK_SIZE,
                                  CLONE_NEWPID | CLONE_NEWUTS| CLONE_NEWIPC|CLONE_NEWNS |SIGCHLD , NULL);
    
            waitpid(clone_pid, NULL, 0);
            printf("this is in %s\n", __func__);
            return 0;
    }
    

    **

    UTS命名空间

    **
    操作如下:
    1.启动UTS命名空间进程,在进程内把UTS的名字命名为alexander;
    2.在进程内启动了bash进程,查看子进程UTS命名空间,为alexander;
    3.退出子进程,子命名空间不存在;
    4.查看主命名空间,为系统的hostname(ubuntu)
    结果如下:

    root@ubuntu:/usr/src/linux-2.6.39/driver/namespace/clone# gcc ipc_clone.c -o clone
    root@ubuntu:/usr/src/linux-2.6.39/driver/namespace/clone# ./clone 
    this is in contain_func, and pid : 1 
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# hostname
    alexander
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# exit
    exit
    this is in main
    root@ubuntu:/usr/src/linux-2.6.39/driver/namespace/clone# hostname
    ubuntu
    root@ubuntu:/usr/src/linux-2.6.39/driver/namespace/clone# 
    

    **

    IPC命名空间

    **
    操作过程如下:

     1. 启动子进程命名空间;
     2. 在子进程命名空间中创建IPC通道;
     3. 在子进程中再启动一个子进程,并查看IPC;
     4. 子命名空间的子命名空间中查看不到上一层命名空间中的IPC通信;
    

    操作如下:

    root@ubuntu:/usr/src/linux-2.6.39/driver/namespace/clone# ./clone 
    this is in contain_func, and pid : 1 
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ipcs -q
    
    ------ Message Queues --------
    key        msqid      owner      perms      used-bytes   messages    
    
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ipcmk -Q
    Message queue id: 0
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ipcs -q
    
    ------ Message Queues --------
    key        msqid      owner      perms      used-bytes   messages    
    0x5f9a3379 0          root       644        0            0           
    
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ./clone 
    this is in contain_func, and pid : 1 
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ipcs -q
    
    ------ Message Queues --------
    key        msqid      owner      perms      used-bytes   messages    
    
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# exit
    exit
    this is in main
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ipcs -q
    
    ------ Message Queues --------
    key        msqid      owner      perms      used-bytes   messages    
    0x5f9a3379 0          root       644        0            0           
    
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ipcrm 0x5f9a3379
    ipcrm: unknown argument: 0x5f9a3379
    usage: ipcrm [ [-q msqid] [-m shmid] [-s semid]
              [-Q msgkey] [-M shmkey] [-S semkey] ... ]
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ipcrm -Q 0x5f9a3379
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ipcs -q
    
    ------ Message Queues --------
    key        msqid      owner      perms      used-bytes   messages    
    
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# exit
    exit
    this is in main
    

    **

    PID命名空间

    **
    操作过程如下:

    1.启动子进程命名空间;
    2.查看子进程命名空间中的进程;
    3.查看子进程命名空间中的proc文件系统
    

    操作如下:

    root@ubuntu:/usr/src/linux-2.6.39/driver/namespace/clone# ./clone 
    this is in contain_func, and pid : 1 
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ps aux
    USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root         1  0.5  0.0   5748  1956 pts/15   S    04:35   0:00 [bash]
    root        13  0.0  0.0   5216  1144 pts/15   R+   04:35   0:00 ps aux
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ps -ef
    UID        PID  PPID  C STIME TTY          TIME CMD
    root         1     0  0 04:35 pts/15   00:00:00 [bash]
    root        14     1  0 04:35 pts/15   00:00:00 ps -ef
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# ls /proc/
    1          cgroups   diskstats    fs          kallsyms    kpageflags     misc     pagetypeinfo  slabinfo       sysvipc      version_signature
    15         cmdline   dma          interrupts  kcore       latency_stats  modules  partitions    softirqs       timer_list   vmallocinfo
    acpi       consoles  driver       iomem       keys        loadavg        mounts   sched_debug   stat           timer_stats  vmstat
    asound     cpuinfo   execdomains  ioports     key-users   locks          mpt      schedstat     swaps          tty          zoneinfo
    buddyinfo  crypto    fb           ipmi        kmsg        mdstat         mtrr     scsi          sys            uptime
    bus        devices   filesystems  irq         kpagecount  meminfo        net      self          sysrq-trigger  version
    root@alexander:/usr/src/linux-2.6.39/driver/namespace/clone# exit
    exit
    this is in main
    

    **

    总结

    **

    上述子命名空间中的操作主要由如下关键宏操作:
    CLONE_NEWPID:创建PID命名空间
    CLONE_NEWUTS:创建UTS命名空间;
    CLONE_NEWIPC:创建新的IPC命名空间;
    CLONE_NEWNS:创建新的文件系统命名空间;
    注意:
    在创建新的IPC命名空间过程中必须指定创建文件系统命名空间,并且挂载新的proc文件系统,否则会使用上一层命名空间中的proc文件系统,这样显示的PID(无论是ps 命令还是top命令)就如上一层命名空间中显示的PID一样的。

    展开全文
  • linux命名空间(namespace)学习(二)

    千次阅读 2018-12-08 08:29:14
    在上一篇博客里面介绍了Linux命名空间的使用,本博客更新的博客中更新下关于linuxUTS命名空间的介绍以及使用方式; UTS命名空间,是关于linux主机命名或者内核版本命名的一套命名空间,在此命名空间中用户感知的是一...

    Linux的UTS命名空间

    在上一篇博客里面介绍了Linux命名空间的使用,本博客更新的博客中更新下关于linuxUTS命名空间的介绍以及使用方式;
    UTS命名空间,是关于linux主机命名或者内核版本命名的一套命名空间,在此命名空间中用户感知的是一个单独命名的的linux主机名称,注意:仅仅是主机名称,如果没有结合其他命名空间操作的话,用户是感知不到一个单独的主机名称的;
    一下是我学习linux的UTS命名空间的一些思路:
    1. UTS命名空间在用户层怎么使用;
    2. UTS命名空间在内核中的应用;
    3. UTS命名空间怎么和用户的PID结合的;

    我会根据以上三个问题一一介绍,可能第二点放在第三点之后讲解,这样组织结构更加清晰;
    **

    1.UTS命名空间在用户层怎么使用

    **
    这一点在我的《linux命名空间(namespace)学习(一)》中博客中有具体的使用方式,在此不赘述;
    **

    2.UTS命名空间怎么和用户的PID结合的;

    **
    UTS命名空间和用户空间和用户PID结合的方式这句话可能有点绕,如果换句话说:UTS命名空间在内核中的task_struct的表示方式,这句话就好多了。task_struct结构在内核中是表示一个唯一PID的一种方式,在内核中task_struct指向总体命名空间的struct nsproxy *nsproxy;结构和所有命名空间建立联系的。而struct nsproxy * nsproxy和内核中的所有类型的命名空间建立联系;
    其中和内核UTS命名空间的数据联系结构如下:
    task_struct结构指向utsnamespace结构的流程
    如上图所示的流程图可以看出task_struct通过nsproxy指针一步可以找到utsnamspace结构。之后对与utsnamespace读写操操作;
    数据结构如下:

    struct task_struct{
    	......
    	struct nsproxy * 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;
            struct net           *net_ns;
            };
     
    struct uts_namespace{
            struct kref kref;
            struct new_utsname name;
            struct user_namespace *user_ns;
    };
    

    **

    3.UTS命名空间在内核中的应用

    **
    关于UTS命名空间在内核中的应用主要涉及如下几点:

     1. UTS命名空间在clone带CLONE_NEWUTS标志过程中如何使用?
     2. struct uts_namespace *copy_utsname(unsigned long flags,
                                       struct task_struct *tsk)
    {
            struct uts_namespace *old_ns = tsk->nsproxy->uts_ns;
            struct uts_namespace *new_ns;
    
            BUG_ON(!old_ns);
            get_uts_ns(old_ns);
    
            if (!(flags & CLONE_NEWUTS))
                    return old_ns;
    
            new_ns = clone_uts_ns(tsk, old_ns);
    
            put_uts_ns(old_ns);
            return new_ns;
    }
    
    

    先回答第一个问题,可能也是最复杂的问题: UTS命名空间在clone带CLONE_NEWUTS标志过程中如何使用?
    首先我们知道在《linux命名空间(namespace)学习(一)》,如果CLONE带CLONE_NEWUTS标志,代表着创建一个新的UTS命名空间。用户子进程命名空间和主进程命名空格键看到的主机名可能是一致的,也可能不一致;主要取决于用户是否使用sethostname函数。但是这时候用户子命名空间和主进程命名空间使用的命名空间却不是同一个物理地址了,为什么呢?为了保证用户子命名空间和主进程命名空间的独立性,这样用户在设置主机名称的时候不会影响到主进程命名空间。主要由copy_utsname函数来起作用。原型如下:

    struct uts_namespace *copy_utsname(unsigned long flags,
                                       struct task_struct *tsk)
    {
            struct uts_namespace *old_ns = tsk->nsproxy->uts_ns;
            struct uts_namespace *new_ns;
    
            BUG_ON(!old_ns);
            get_uts_ns(old_ns);
    
            if (!(flags & CLONE_NEWUTS))
                    return old_ns;
    
            new_ns = clone_uts_ns(tsk, old_ns);
    
            put_uts_ns(old_ns);
            return new_ns;
    }
    函数参数:
    	flags:clone函数调用的参数;
    	tsk:要克隆的主进程的task_struct;
    函数返回值:
    	struct uts_name* 类型,返回的是UTS命名空间的地址;
    函数作用:
    	先判断flags是否有CLONE_NEWUTS结构;
    	1.没有,则返回老的uts_namespace;
    	2.有,先申请一块内存再吧原来的uts_namespace拷贝给新的内存;
    注意:在没有CLONE_NEWUTS结构情况下会把uts_namespace->kref加一,否则不加一;
    

    以上可以看出,如果clone时候flags标志为没有CLONE_NEWUTS标志,只需要把旧的uts_namespace引用计数加一并返回就可以了,如果有CLONE_NEWUTS标志则需要申请一段内存区域并且返回就OK了。这样问题二的答案也就有了。

    展开全文
  • linux命名空间UTS 总结

    千次阅读 2017-06-06 01:21:37
    本文介绍linux上域名命名空间的例子和试验结果。

    #define _GNU_SOURCE
    #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 child_stack[STACK_SIZE];
    char *const child_args[] = {
    "/bin/bash",
    NULL
    };
    
    int child_main(void *args)
    {
            printf("in child process \n");
            sethostname("NewNameSpace", 20);
            execv(child_args[0], child_args);
            return 1;
    }
    
    int main()
    {
            printf("process start: \n");
    
            int child_pid = clone(child_main, child_stack + STACK_SIZE, CLONE_NEWUTS|SIGCHLD, NULL);
            waitpid(child_pid, NULL, 0);
            printf("end \n");
            return 0;
    }


    1、UTS命名空间,提供了主机名和域名的隔离。

    运行结果如下:

    [root@localhost code]# ./a.out 
    process start: 
    in child process 
    [root@NewNameSpace code]# 
    [root@NewNameSpace code]# exit
    exit
    end 
    [root@localhost code]# 

    [root@localhost code]# uname -a
    Linux NewNameSpace 3.10.0-514.6.1.el7.x86_64 #1 SMP Wed Jan 18 13:06:36 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
    [root@localhost code]# 


    展开全文
  • linux命名空间(namespace)学习(三)

    千次阅读 2018-12-08 11:09:40
    LinuxPID命名空间学习 通过对于前两节的学习我们知道Linux内核使用task_struct结构来表示和管理进程,这个数据结构里面存放了很多有关于PID如何管理的数据,可以这么说,Linux内核所有有关进程管理的数据结构都和此...

    LinuxPID命名空间学习

    通过对于前两节的学习我们知道Linux内核使用task_struct结构来表示和管理进程,这个数据结构里面存放了很多有关于PID如何管理的数据,可以这么说,Linux内核所有有关进程管理的数据结构都和此数据结构有关。该数据结构存放在include/linux/sched.h头文件里,并且这个数据结构比较大,就不一一列举了。实际上一一列举也没有什么意思,因这个数据结构过于庞大导致列举出来连笔者都感到头大----可以举出这么一个例子:这个数据结构占用内核1.7K的空间,可想有多么庞大。但是不需要担心,可以把此数据结构分块划分的话,就简单很多了。话不多说我会根据如下来结构体系来介绍:

     1. 进程类型
     2. PID的命名空间;
     3.管理 PID有关的数据结构
    

    进程类型

    进程如何划分呢?我们可以把进程划分为如下四种类型:

     1.普通PID:
     	这是Linux对于每一个进程都使用的划分,每一个进程都分配给一个PID,每一个PID都对应一个task_struct,每一个task_struct对应着相应的命名空间,和PID类型(先做了解)。
     2.TGID:
     	线程组ID,这个是线程的定义,这个定义在clone时候使用CLONE_THREAD函数调用的时候进行:在一个进程中,如果以CLONE_THREAD标志来调用clone建立的进程就是该进程的一个线程,它们处于一个线程组,该线程组的ID叫做TGID。处于相同的线程组中的所有进程都有相同的TGID;线程组组长的TGID与其PID相同;一个进程没有使用线程,则其TGID与PID也相同。
     3.PGID:
     	另外,独立的进程可以组成进程组(使用setpgrp系统调用),进程组可以简化向所有组内进程发送信号的操作,例如用管道连接的进程处在同一进程组内。进程组ID叫做PGID,进程组内的所有进程都有相同的PGID,等于该组组长的PID。
     4.SID:
     	几个进程组可以合并成一个会话组(使用setsid系统调用),可以用于终端程序设计。会话组中所有进程都有相同的SID。
    

    PID命名空间

    命名空间是为操作系统层面的虚拟化机制提供支撑,目前实现的有六种不同的命名空间,分别为mount命名空间、UTS命名空间、IPC命名空间、用户命名空间、PID命名空间、网络命名空间。命名空间简单来说提供的是对全局资源的一种抽象,将资源放到不同的容器中(不同的命名空间),各容器彼此隔离。命名空间有的还有层次关系,如PID命名空间,图1 为命名空间的层次关系图。

    图1 命名空间的层次关系
    在上图有四个命名空间,一个父命名空间衍生了两个子命名空间,其中的一个子命名空间又衍生了一个子命名空间。以PID命名空间为例,由于各个命名空间彼此隔离,所以每个命名空间都可以有 PID 号为 1 的进程;但又由于命名空间的层次性,父命名空间是知道子命名空间的存在,因此子命名空间要映射到父命名空间中去,因此上图中 level 1 中两个子命名空间的六个进程分别映射到其父命名空间的PID 号5~10。

    命名空间增大了 PID 管理的复杂性,对于某些进程可能有多个PID——在其自身命名空间的PID以及其父命名空间的PID,凡能看到该进程的命名空间都会为其分配一个PID。因此就有:

    全局ID:

    在内核本身和初始命名空间中具有唯一的ID表示唯一的进程。内核中的init进程就是初始命名空间。系统为每一个进程分配了ID号来标示不同的进程,无论是在一级命名空间还是在二级命名空间中的进程,都在初始命名空间进程中都申请了一个ID号用于管理。这样在父命名空间中就可以看到子命名空间中的进程了。
    

    局部ID

    也可以说是子命名空间中看到的ID号,这个ID只能在子命名空间中有用,在父命名空间中没有作用。
    

    进程ID管理数据结构

    Linux 内核在设计管理ID的数据结构时,要充分考虑以下因素:

    1.如何快速地根据进程的 task_struct、ID类型、命名空间找到局部ID
    2.如何快速地根据局部ID、命名空间、ID类型找到对应进程的 task_struct
    3.如何快速地给新进程在可见的命名空间内分配一个唯一的 PID
    如果将所有因素考虑到一起,将会很复杂,下面将会由简到繁设计该结构。
    介绍的结构如下:

     1. 一个PID只对应一个task_struct结构;
     2. 加入TGID/PGID/SID管理的PID管理;
     3. 加入命名空间的PID管理
    

    一个PID对应一个task_struct结构

    如果不考虑一个进程对应的TGID/PGID/SID,也不考虑一个进程对应的命名空间设计,我们可以对于进程的数据结构进行如下设计:
    一个进程对应了一个task_struct结构,其中每一个PID 中的nr表示PID号即为进程号,PID 结构中的pid_chain代表PID散列表的节点。
    进程的设计一

    上述设计核心思想如下:
    1.一个task_struct 中存放着pid_link结构体,指向struct pid结构。
    2.PID结构里面存放着PID 号(即为nr),也存放着指向pid_link的指针和PID散列表的节点的节点。
    3.每一个PID的申请和释放都是通过pid_hash(PID散列表)和pid_map来进行管理的。
    4.对于每一个PID的查找也是通过pid_hash来管理的;
    数据结构如下:

    struct task_struct {
        //...
        struct pid_link pids;
        //...
    };
    
    struct pid_link {
        struct hlist_node node;  
        struct pid *pid;          
    };
    
    struct pid {
        struct hlist_head tasks;        //指回 pid_link 的 node
        int nr;                       //PID
        struct hlist_node pid_chain;    //pid hash 散列表结点
    };
    

    上述两个主要的数据结构还有两个没有介绍:
    pid_hash[]:是PID的hash散列表,用于管理和查找pid结构,主要通过pid号来进行关键索引找到PID结构。然后找到task_struct结构,主要查找有一下四步:

     1. 通过PID号,索引pid_hash[],找到struct pid的pid_chain结构;
     2. 通过pid_chain找到struct pid结构;
     3. struct pid结构中有tasks指向,task_struct->plink.node;
     4. 通过container_of查找到struct task_struct结构;
    

    pid_map:PID位图表示,主要用于申请和释放未使用的PID号,这样不用遍历pid_hash结构也能够找到未使用的PID号。

    加入TGID/PGID/SID管理的PID管理

    加入TGID/PGID/SID管理的PID管理稍微比较复杂一点,在上述基础上我们知道struct pid结构可以索引到task_struct结构,但是如何加入TGID/PGID/SID的管理呢?可以从如下角度考虑下问题:

     1. 如何通过进程本身的task_struct 索引到自身的所属TGID/PGID/SID的struct PID 结构?
     2. 一个线程组或者一个进程组或者一个组里面的线程主ID或者进程组ID或者组ID怎么索引到其下所有的线程,进程,组中所有的进程?
    

    以上两点的解决方案如下图:

    加入TGID/PGID/SID管理的PID管理ruc
    对于上述的两点疑问可以做如下解答:

     1. 在task_struct结构里面增加struct pid_link数组到至少四个,第一个索引自身进程的struct pid结构,第二个索引线程组ID,第三个索引PGID,第四个索引SID。可以通过一次索引查询到自身task_struct的PID,TGID,PGID,SID结构的task_struct结构。
     2. 每一个自身的进程的PID结构把tasks数组增加至至少四个,第一个索引自身的task_struct ,第二个索引以自己为主进程的下面挂载多少个线程的task_struct,第三个索引以自己为主进程下面挂载多少个gid..... 其中hlist_head tasks[index]以struct task_struct->pid_link[index].hlist_node为节点.
    

    数据结构设计如下:

    enum pid_type
    {
        PIDTYPE_PID,
        PIDTYPE_PGID,
        PIDTYPE_SID,
        PIDTYPE_MAX
    };
    
    struct task_struct {
        //...
        pid_t pid;     //PID
        pid_t tgid;    //thread group id
    
        struct task_struct *group_leader;   // threadgroup leader
    
        struct pid_link pids[PIDTYPE_MAX];
    
        //...
    };
    
    struct pid_link {
        struct hlist_node node;  
        struct pid *pid;          
    };
    
    struct pid {
        struct hlist_head tasks[PIDTYPE_MAX];
        int nr;                         //PID
        struct hlist_node pid_chain;    // pid hash 散列表结点
    };
    

    **

    增加PID命名空间的PID表示结构

    **
    再回到PID命名空间的讨论范畴,通过本文中对于PID命名空间的介绍我们知道每一个命名空间中其PID分配是相对独立的,在父命名空间中可以看到子命名空间中的进程,父命名空间中看到的进程号是父命名空间分配的,子命名空间中看到的进程号是子命名空间分配的。
    可能会有一下疑问:

     1. 子命名空间中的进程怎么会索引到父命名空间中?
     2. 子命名空间中怎么会感知父命名空间的存在呢?
     3. 父命名空间如何会知道子命名空间中的进程呢?
     4. 父命名空间中的进程如何给子命名空间中的进程分配PID呢?
    

    为了回答以上问题,我们先从第四个问题开始讨论:
    为了使父命名空间给子命名空间中的进程分配进程号,Linux内核在命名空间设计中把pid_map结构放入到命名空间中结构,这样每一个父命名空间中的结构就能够给子命名空间中的进程分配ID了,如下所示:

    struct pid_namespace {
            struct kref kref;
            struct pidmap pidmap[PIDMAP_ENTRIES];
            int last_pid;
            struct task_struct *child_reaper;
            struct kmem_cache *pid_cachep;
            unsigned int level;
            struct pid_namespace *parent;
    #ifdef CONFIG_PROC_FS
            struct vfsmount *proc_mnt;
    #endif
    #ifdef CONFIG_BSD_PROCESS_ACCT
            struct bsd_acct_struct *bacct;
    #endif
    };
    以上数据结构还回答了我们第二个问题:子命名空间怎么感知父命名空间的存在
    

    父命名空间如何会知道子命名空间中的进程呢?

    我们知道同一个父命名空间中的进程ID和子命名空间中的ID互相不影响,而且敷命名空间的和子命名空间是不相同的,这样我们就可以在设计数据结构的时候把两者设计在一起,只要找到设计的数据结构就可以通过pid_hash得到struct upid结构。
    上面提到的pid_hash索引的功能有所变化,之前提交通过pid_hash表通过PID值可以索引到struct pid结构,但是现在我们通过hash表先索引到struct upid结构,再通过upid结构和namespace的level值所引到pid结构。进一步所引到task_struct结构
    如下所示:

    struct upid {
            /* Try to keep pid_chain in the same cacheline as nr for find_vpid */
            int nr;
            struct pid_namespace *ns;
            struct hlist_node pid_chain;
    };
    

    以下图片会帮助我们回答以上所有问题,举例来说,在level 2 的某个命名空间上新建了一个进程,分配给它的 pid 为45,映射到 level 1 的命名空间,分配给它的 pid 为 134;再映射到 level 0 的命名空间,分配给它的 pid 为289,对于这样的例子,如图4所示为其表示:在这里插入图片描述
    图中关于如果分配唯一的 PID 没有画出,但也是比较简单,与前面两种情形不同的是,这里分配唯一的 PID 是有命名空间的容器的,在PID命名空间内必须唯一,但各个命名空间之间不需要唯一。
    数据结构设计如下:

    struct pid
    {
        unsigned int level;  
        /* lists of tasks that use this pid */
        struct hlist_head tasks[PIDTYPE_MAX];
        struct upid numbers[1];
    };
    
    struct upid {
        int nr;
        struct pid_namespace *ns;
        struct hlist_node pid_chain;
    };
    
    

    以上摘自:https://www.cnblogs.com/hazir/p/linux_kernel_pid.html

    展开全文
  • linux命名空间(namespace)学习(四)

    千次阅读 2018-12-09 11:03:30
    Linux的PID命名空间的学习 上一篇博客更新了linux的PID命名空间的数据结构,本节讲一下关于PID命名空间的相关操作的函数。会先从需求开始讲起来,慢慢串联成一个线。 回想一下,我们在应用空间中获取到的是一个PID号...
  • 时间 2014-12-25 16:26:47 极客头条 ...主题 Linux 【编者的话】Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。而 LXC所实现
  • linux 网络命名空间 Network namespaces

    万次阅读 2017-04-19 16:20:01
    Linux命名空间是一个相对较新的内核功能,对于实现容器至关重要。 命名空间将全局系统资源包装到一个抽象中,该抽象只会与命名空间中的进程绑定,从而提供资源隔离。 在本文中,我将讨论网络命名空间并展示一个实际...
  • linux中的网络命名空间的使用

    千次阅读 2018-09-03 22:29:24
    背景 项目中使用了网络命名空间,用来隔离...linux命名空间 命名空间(Linux namespace)是linux内核针对实现容器虚拟化映入的一个特性。 我们创建的每个容器都有自己的命名空间,运行在其中的应用都像是在独立...
  • Linux 网络命名空间

    千次阅读 2017-04-09 09:59:58
    网络命名空间 虚拟网络创建 iproute2 创建新的网络命名空间 显示所有的虚拟网络命名空间 进入虚拟网络环境 设置虚拟网络环境net0的veth0设备处于激活状态 为虚拟网络环境net0的veth0设备增加IP地址 连接两个网络环境...
  • 命名空间(namespace)...通过Linux命名空间,能够把Linux有限的内核资源(进程号、通信资源、网络资源等)合理分配给各个用户的进程,而不互相干扰。 Linux的网络命名空间(network namespace)用以在一个Linux主...
  • 记得看《深入Linux内核架构》时,里面有讲到关于命名空间的概念,但是现在却基本上弯光了,唉。所以今天特意自己翻看一下内核4.2代码,整理一下命名空间中关于pid管理的部分,等什么时候有空了,再去翻看那本著作吧...
  • Linux网络命名空间

    千次阅读 2013-03-11 22:07:20
    网络的命名空间,可以具有网络接口和操作彼此独立的 不同 路由表和单独的实例。 创建网络空间: ip netns add 查看网络空间列表: ip netns list 接口分配给命名空间 配置...
  • https://blog.csdn.net/gatieme/article/details/51383322 Linux命名空间详解--Linux进程的管理与调度(二) 传统上,在Linux以及其他衍生的UNIX变体中,许多资源是全局管理的。命名空间提供了一种不同的解决方案...
  • 作为开源Container技术代表的Docker,它跟Linux内核的Namespace和...在前面的文章中,我们曾经体验过如何使用chroot和LXC,在接下来几篇文章中,我们将会使用unshare命令来演示Linux内核的命名空间到底是怎么玩的。
  • Linux命名空间详解--Linux进程的管理与调度(二)

    万次阅读 多人点赞 2016-05-12 13:20:26
    日期 内核版本 架构 作者 GitHub CSDN 2016-05-12 ... Linux-进程管理与调度 Linux Namespaces机制提供一种资源隔离方案。 PID,IPC,Network等系统资源不再是全局性的,而是属于特定的Namespace。每个Name
  • Linux内核IPC机制 在Linux内核中IPC全名称之为进程间通信机制,共分为多种...信号量,共享内存,消息队列是在内核中使用了IPC命名空间实现,由统一的键值管理(之前博客中有讲解过IDR机制管理键值),实现起来比较简...
  • 【转】Linux查看进程的命名空间

    千次阅读 2019-08-26 10:25:29
    Linux命名空间机制提供了一种资源隔离的解决方案。PID,IPC,Network等系统资源不再是全局性的,而是属于特定的Namespace。Linux Namespace机制为实现基于容器的虚拟化技术提供了很好的基础,LXC(Linux containers...
  • linux命名管道

    千次阅读 2017-09-05 17:46:52
    ●无名管道 主要用于父进程与子进程之间,或者两个兄弟进程之间。在linux系统中可以通过系统调用建立起一个单向的通信
  • 作为开源Container技术代表的Docker,它跟Linux内核的Namespace和Cgroup两大特性密不可分。物有本末,事有终始。知所先后,则近道矣。理解Linux的这两大特性将有助于我们更深入的理解Docker。 在本文中我们将会...
  • 作为开源Container技术代表的Docker,它跟Linux内核的Namespace和Cgroup两大特性密不可分。物有本末,事有终始。知所先后,则近道矣。理解Linux的这两大特性将有助于我们更深入的理解Docker。 在本文中我们将会...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 130,354
精华内容 52,141
关键字:

linux命名空间

linux 订阅