Linux Namespace 入門系列:Namespace API
阿新 • • 發佈:2020-03-29
`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
#