linux程式碼之namespace

xiaozhiwise發表於2020-12-15

/*
 * 2020/12/15    11:58    yin
 */

/*
 * 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,且不會對宿主機產生任何影響,
    由此達到主機名和域名的隔離效果。


/*
 * 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,而當前程式保持不變
        

 

相關文章