Linux Namespace系列(01):Namespace概述
Namespace是對全局系統資源的一種封裝隔離,使得處于不同namespace的進程擁有獨立的全局系統資源,改變一個namespace中的系統資源只會影響當前namespace里的進程,對其他namespace中的進程沒有影響。
下面的所有例子都在ubuntu-server-x86_64 16.04下執行通過
Linux內核支持的namespaces
目前,Linux內核里面實現了7種不同類型的namespace。
名稱 宏定義 隔離內容 Cgroup CLONE_NEWCGROUP Cgroup root directory (since Linux 4.6) IPC CLONE_NEWIPC System V IPC, POSIX message queues (since Linux 2.6.19) Network CLONE_NEWNET Network devices, stacks, ports, etc. (since Linux 2.6.24) Mount CLONE_NEWNS Mount points (since Linux 2.4.19) PID CLONE_NEWPID Process IDs (since Linux 2.6.24) User CLONE_NEWUSER User and group IDs (started in Linux 2.6.23 and completed in Linux 3.8) UTS CLONE_NEWUTS Hostname and NIS domain name (since Linux 2.6.19)注意: 由于Cgroup namespace在4.6的內核中才實現,并且和cgroup v2關系密切,現在普及程度還不高,比如docker現在就還沒有用它,所以在namespace這個系列中不會介紹Cgroup namespace。
查看進程所屬的namespaces
系統中的每個進程都有/proc/[pid]/ns/這樣一個目錄,里面包含了這個進程所屬namespace的信息,里面每個文件的描述符都可以用來作為setns函數(后面會介紹)的參數。
#查看當前bash進程所屬的namespace dev@ubuntu:~$ ls -l /proc/$$/ns total 0 lrwxrwxrwx 1 dev dev 0 7月 7 17:24 cgroup -> cgroup:[4026531835] #(since Linux 4.6) lrwxrwxrwx 1 dev dev 0 7月 7 17:24 ipc -> ipc:[4026531839] #(since Linux 3.0) lrwxrwxrwx 1 dev dev 0 7月 7 17:24 mnt -> mnt:[4026531840] #(since Linux 3.8) lrwxrwxrwx 1 dev dev 0 7月 7 17:24 net -> net:[4026531957] #(since Linux 3.0) lrwxrwxrwx 1 dev dev 0 7月 7 17:24 pid -> pid:[4026531836] #(since Linux 3.8) lrwxrwxrwx 1 dev dev 0 7月 7 17:24 user -> user:[4026531837] #(since Linux 3.8) lrwxrwxrwx 1 dev dev 0 7月 7 17:24 uts -> uts:[4026531838] #(since Linux 3.0)- 上面每種類型的namespace都是在不同的Linux版本被加入到/proc/[pid]/ns/目錄里去的,比如pid namespace是在Linux 3.8才被加入到/proc/[pid]/ns/里面,但這并不是說到3.8才支持pid namespace,其實pid namespace在2.6.24的時候就已經加入到內核了,在那個時候就可以用pid namespace了,只是有了/proc/[pid]/ns/pid之后,使得操作pid namespace更方便了
- 雖然說cgroup是在Linux 4.6版本才被加入內核,可是在Ubuntu 16.04上,盡管內核版本才4.4,但也支持cgroup namespace,估計應該是Ubuntu將4.6的cgroup namespace這部分代碼patch到了他們的4.4內核上。
- 以ipc:[4026531839]為例,ipc是namespace的類型,4026531839是inode number,如果兩個進程的ipc namespace的inode number一樣,說明他們屬于同一個namespace。這條規則對其他類型的namespace也同樣適用。
- 從上面的輸出可以看出,對于每種類型的namespace,進程都會與一個namespace ID關聯。
跟namespace相關的API
和namespace相關的函數只有三個,這里簡單的看一下,后面介紹UTS namespace的時候會有詳細的示例
clone: 創建一個新的進程并把他放到新的namespace中
int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg);flags: 指定一個或者多個上面的CLONE_NEW*(當然也可以包含跟namespace無關的flags), 這樣就會創建一個或多個新的不同類型的namespace, 并把新創建的子進程加入新創建的這些namespace中。setns: 將當前進程加入到已有的namespace中
int setns(int fd, int nstype);fd: 指向/proc/[pid]/ns/目錄里相應namespace對應的文件,表示要加入哪個namespacenstype:指定namespace的類型(上面的任意一個CLONE_NEW*):1. 如果當前進程不能根據fd得到它的類型,如fd由其他進程創建,并通過UNIX domain socket傳給當前進程,那么就需要通過nstype來指定fd指向的namespace的類型2. 如果進程能根據fd得到namespace類型,比如這個fd是由當前進程打開的,那么nstype設置為0即可unshare: 使當前進程退出指定類型的namespace,并加入到新創建的namespace(相當于創建并加入新的namespace)
int unshare(int flags);flags:指定一個或者多個上面的CLONE_NEW*,這樣當前進程就退出了當前指定類型的namespace并加入到新創建的namespaceclone和unshare的區別
clone和unshare的功能都是創建并加入新的namespace, 他們的區別是:
- unshare是使當前進程加入新的namespace
- clone是創建一個新的子進程,然后讓子進程加入新的namespace,而當前進程保持不變
其它
當一個namespace中的所有進程都退出時,該namespace將會被銷毀。當然還有其他方法讓namespace一直存在,假設我們有一個進程號為1000的進程,以ipc namespace為例:
參考
- https://segmentfault.com/a/1190000006908272
- overview of Linux namespaces
- Namespaces in operation, part 1: namespaces overview
總結
以上是生活随笔為你收集整理的Linux Namespace系列(01):Namespace概述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【网址收藏】helm charts gi
- 下一篇: 【网址收藏】linux namespac