1. 程式人生 > >Linux Namespace 入門系列:Namespace API

Linux Namespace 入門系列:Namespace API

`Linux Namespace` 是 Linux 提供的一種核心級別環境隔離的方法。用官方的話來說,Linux Namespace 將全域性系統資源封裝在一個抽象中,從而使 namespace 內的程序認為自己具有獨立的資源例項。這項技術本來沒有掀起多大的波瀾,是容器技術的崛起讓他重新引起了大家的注意。 Linux Namespace 有如下 6 個種類: | **分類** | **系統呼叫引數** | **相關核心版本** | | ------------------ | ---------------- | ------------------------------------------------------------ | | Mount namespaces | CLONE_NEWNS | [Linux 2.4.19](http://lwn.net/2001/0301/a/namespaces.php3) | | UTS namespaces | CLONE_NEWUTS | [Linux 2.6.19](http://lwn.net/Articles/179345/) | | IPC namespaces | CLONE_NEWIPC | [Linux 2.6.19](http://lwn.net/Articles/187274/) | | PID namespaces | CLONE_NEWPID | [Linux 2.6.24](http://lwn.net/Articles/259217/) | | Network namespaces | CLONE_NEWNET | [始於Linux 2.6.24 完成於 Linux 2.6.29](http://lwn.net/Articles/219794/) | | User namespaces | CLONE_NEWUSER | [始於 Linux 2.6.23 完成於 Linux 3.8](http://lwn.net/Articles/528078/) | namespace 的 API 由三個系統呼叫和一系列 `/proc` 檔案組成,本文將會詳細介紹這些系統呼叫和 `/proc` 檔案。為了指定要操作的 namespace 型別,需要在系統呼叫的 flag 中通過常量 `CLONE_NEW*` 指定(包括 `CLONE_NEWIPC`,`CLONE_NEWNS`, `CLONE_NEWNET`,`CLONE_NEWPID`,`CLONE_NEWUSER` 和 `CLONE_NEWUTS),可以指定多個常量,通過 **|**(位或)操作來實現。 簡單描述一下三個系統呼叫的功能: + **clone()** : 實現執行緒的系統呼叫,用來建立一個新的程序,並可以通過設計上述系統呼叫引數達到隔離的目的。 + **unshare()** : 使某程序脫離某個 namespace。 + **setns()** : 把某程序加入到某個 namespace。 具體的實現原理請往下看。 ## 1. clone() ---- `clone()` 的原型如下: ```c int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg); ``` + **child_func** : 傳入子程序執行的程式主函式。 + **child_stack** : 傳入子程序使用的棧空間。 + **flags** : 表示使用哪些 `CLONE_*` 標誌位。 + **args** : 用於傳入使用者引數。 `clone()` 與 `fork()` 類似,都相當於把當前程序複製了一份,但 `clone()` 可以更細粒度地控制與子程序共享的資源(其實就是通過 flags 來控制),包括虛擬記憶體、開啟的檔案描述符和訊號量等等。一旦指定了標誌位 `CLONE_NEW*`,相對應型別的 namespace 就會被建立,新建立的程序也會成為該 namespace 中的一員。 clone() 的原型並不是最底層的系統呼叫,而是封裝過的,真正的系統呼叫核心實現函式為 `do_fork()`,形式如下: ```c long do_fork(unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr) ``` 其中 `clone_flags` 可以賦值為上面提到的標誌。 下面來看一個例子: ```c /* demo_uts_namespaces.c Copyright 2013, Michael Kerrisk Licensed under GNU General Public License v2 or later Demonstrate the operation of UTS namespaces. */ #define _GNU_SOURCE #