是什么?
linux的機制有點類似于數(shù)據(jù)庫中的,可以為不同的進程提供各自的命名空間,命名空間互相隔離,進程跑在自己的中資源互相隔離 。
嵌入式進階教程分門別類整理好了,看的時候十分方便,由于內(nèi)容較多 , 這里就截取一部分圖吧 。
需要的朋友私信【內(nèi)核】即可領(lǐng)取 。
內(nèi)核學習地址:Linux內(nèi)核源碼/內(nèi)存調(diào)優(yōu)/文件系統(tǒng)/進程管理/設(shè)備驅(qū)動/網(wǎng)絡(luò)協(xié)議棧-學習視頻教程-騰訊課堂
使用了的機制,將進程隔離在某個中,而在某一個命名空間內(nèi)的進程可以感知到其他進程的存在,但是對空間外部的進程一無所知 。以一種輕量級的方式實現(xiàn)了虛擬化技術(shù) 。
提供了多種資源的隔離:
clone(…flag…)
所隔離的資源
根目錄
IPC
V IPC,POSIX 消息隊列
網(wǎng)絡(luò)設(shè)備、協(xié)議棧、端口等
Mount
掛載點
PID
進程 ID
User
用戶和組 ID
UTS
主機名和域名
多種類型的資源隔離可以讓我們從文件系統(tǒng)開始,到進程通信、網(wǎng)絡(luò)通信、用戶權(quán)限管理、主機管理,一步步地實現(xiàn)各方面資源的隔離 , 使進程運行在一個虛擬化的環(huán)境中 。本文討論的實現(xiàn)針對Linux內(nèi)核3.8及其以后的版本 。
下面我們針對六種命名空間的API做一些實例講解,親身體驗隔離的實現(xiàn)底層機制 。
2 實戰(zhàn)
關(guān)于的系統(tǒng)調(diào)用主要有三個:
結(jié)合一段代碼來介紹幾個
#define _GNU_SOURCE#include #include #include #include #include #include#define STACK_SIZE (1024 * 1024)static char container_stack[STACK_SIZE]; char* const container_args[] = {"/bin/bash",NULL}; int container_main(void* arg){printf("Container - inside the container!n");execv(container_args[0], container_args);printf("Something's wrong!n");return 1;} int main(){printf("Parent - start a container!n");int container_pid = clone(container_main, container_stack+STACK_SIZE, SIGCHLD, NULL);waitpid(container_pid, NULL, 0);printf("Parent - container stopped!n");return 0;}
2.1 UTS
#define _GNU_SOURCE#include #include #include #include #include #include#define STACK_SIZE (1024 * 1024)static char container_stack[STACK_SIZE]; char* const container_args[] = {"/bin/bash",NULL}; int container_main(void* arg){printf("Container - inside the container!n");sethostname("container",10);execv(container_args[0], container_args);printf("Something's wrong!n");return 1;} int main(){printf("Parent - start a container!n");int container_pid = clone(container_main, container_stack+STACK_SIZE, SIGCHLD | CLONE_NEWUTS, NULL);waitpid(container_pid, NULL, 0);printf("Parent - container stopped!n");return 0;}
已經(jīng)變了
[root@iZbp1d4tisi44j6vxze02fZ tmp]# vi c1.c[root@iZbp1d4tisi44j6vxze02fZ tmp]# gcc c1.c[root@iZbp1d4tisi44j6vxze02fZ tmp]# ./a.outParent - start a container!Container - inside the container![root@container tmp]# hostnamecontainer[root@container tmp]# uname -ncontainer[root@container tmp]# exitexitParent - container stopped![root@iZbp1d4tisi44j6vxze02fZ tmp]#
2.2 UTS
IPC全稱 Inter- ,是Unix/Linux下進程間通信的一種方式,IPC有共享內(nèi)存、信號量、消息隊列等方法 。所以,為了隔離,我們也需要把IPC給隔離開來 , 這樣,只有在同一個下的進程才能相互通信 。
如果你熟悉IPC的原理的話,你會知道,IPC需要有一個全局的ID,即然是全局的 , 那么就意味著我們的需要對這個ID隔離linux消息隊列使用場景,不能讓別的的進程看到 。
【Linux內(nèi)核Namespace隔離測試code】#define _GNU_SOURCE#include #include #include #include #include #include#define STACK_SIZE (1024 * 1024)static char container_stack[STACK_SIZE]; char* const container_args[] = {"/bin/bash",NULL}; int container_main(void* arg){printf("Container - inside the container!n");sethostname("container",10);execv(container_args[0], container_args);printf("Something's wrong!n");return 1;} int main(){printf("Parent - start a container!n");int container_pid = clone(container_main, container_stack+STACK_SIZE,SIGCHLD | CLONE_NEWUTS | CLONE_NEWIPC, NULL);waitpid(container_pid, NULL, 0);printf("Parent - container stopped!n");return 0;}
ipcs用法 ipcs -a 默認的輸出信息 打印出當前系統(tǒng)中所有的進程間通信方式的信息 ipcs -m 打印出使用共享內(nèi)存進行進程間通信的信息 ipcs -q 打印出使用消息隊列進行進程間通信的信息 ipcs -s 打印出使用信號進行進程間通信的信息
創(chuàng)建查詢ipcs
[root@iZbp1d4tisi44j6vxze02fZ tmp]# ipcmk -QMessage queue id: 0[root@iZbp1d4tisi44j6vxze02fZ tmp]# ipcs -q------ Message Queues --------keymsqidownerpermsused-bytesmessages0x3b786aa7 0root64400
查看所有ipcs
[root@iZbp1d4tisi44j6vxze02fZ tmp]# ipcs -a------ Message Queues --------keymsqidownerpermsused-bytesmessages0x3b786aa7 0root64400------ Shared Memory Segments --------keyshmidownerpermsbytesnattchstatus0x00000000 65536root6005242882dest0x00000000 229377root6005242882dest0x00000000 7143426root600167772162dest0x00802c81 400392195mingjie.gm 6005660x00000000 491524root6005242882dest0x00000000 212926469mingjie.gm 64029286401640x00000000 212959238mingjie.gm 6401677721600 820x00000000 884743root6005242882dest0x00000000 212992008mingjie.gm 64013848576820xb4ce0a78 213024777mingjie.gm 64012288820x00803069 388169738mingjie.gm 600566#define _GNU_SOURCE------ Semaphore Arrays --------keysemidownerpermsnsems0x671cfa8c 6422528mingjie.gm 6401520x671cfa8d 6455297mingjie.gm 6401520x671cfa8e 6488066mingjie.gm 640152
執(zhí)行程序
[root@iZbp1d4tisi44j6vxze02fZ tmp]# gcc c2.c -o ipc[root@iZbp1d4tisi44j6vxze02fZ tmp]# ./ipcParent - start a container!Container - inside the container![root@container tmp]#[root@container tmp]# ipcs -a------ Message Queues --------keymsqidownerpermsused-bytesmessages------ Shared Memory Segments --------keyshmidownerpermsbytesnattchstatus------ Semaphore Arrays --------keysemidownerpermsnsems
IPC已經(jīng)被隔離了!
2.3 PID
#define _GNU_SOURCE#include #include #include #include #include #include#define STACK_SIZE (1024 * 1024)static char container_stack[STACK_SIZE]; char* const container_args[] = {"/bin/bash",NULL}; int container_main(void* arg){printf("Container [%5d] - inside the container!n", getpid());sethostname("container",10);execv(container_args[0], container_args);printf("Something's wrong!n");return 1;} int main(){printf("Parent - start a container!n");int container_pid = clone(container_main, container_stack+STACK_SIZE,SIGCHLD | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID, NULL);waitpid(container_pid, NULL, 0);printf("Parent - container stopped!n");return 0;}
運行結(jié)果如下(我們可以看到,子進程的pid是1了):
[root@iZbp1d4tisi44j6vxze02fZ tmp]# gcc c3.c -o pid[root@iZbp1d4tisi44j6vxze02fZ tmp]# ./pidParent - start a container!Container [1] - inside the container![root@container tmp]# echo $
你可能會問,PID為1有個毛用?。課頤侵??nbsp;, 在傳統(tǒng)的UNIX系統(tǒng)中,PID為1的進程是init,地位非常特殊 。他作為所有進程的父進程,有很多特權(quán)(比如:屏蔽信號等),另外 , 其還會檢查所有進程的狀態(tài),我們知道 , 如果某個子進程脫離了父進程(父進程沒有wait它),那么init就會負責回收資源并結(jié)束這個子進程 。所以,要做到進程空間的隔離 , 首先要創(chuàng)建出PID為1的進程,最好就像那樣,把子進程的PID在容器內(nèi)變成1 。
但是 , 我們會發(fā)現(xiàn)linux消息隊列使用場景,在子進程的shell里輸入ps,top等命令,我們還是可以看得到所有進程 。說明并沒有完全隔離 。這是因為,像ps, top這些命令會去讀/proc文件系統(tǒng),所以 , 因為/proc文件系統(tǒng)在父進程和子進程都是一樣的,所以這些命令顯示的東西都是一樣的 。
所以 , 我們還需要對文件系統(tǒng)進行隔離 。
2.4 Mount
下面的例程中,我們在啟用了mount 并在子進程中重新mount了/proc文件系統(tǒng) 。
#define _GNU_SOURCE#include #include #include #include #include #include#define STACK_SIZE (1024 * 1024)static char container_stack[STACK_SIZE]; char* const container_args[] = {"/bin/bash",NULL}; int container_main(void* arg){printf("Container [%5d] - inside the container!n", getpid());sethostname("container",10);/* 重新mount proc文件系統(tǒng)到 /proc下 */system("mount -t proc proc /proc");execv(container_args[0], container_args);printf("Something's wrong!n");return 1;} int main(){printf("Parent [%5d] - start a container!n", getpid());int container_pid = clone(container_main, container_stack+STACK_SIZE,SIGCHLD | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS, NULL);waitpid(container_pid, NULL, 0);printf("Parent - container stopped!n");return 0;}
運行結(jié)果如下:
[root@iZbp1d4tisi44j6vxze02fZ tmp]# gcc c4.c[root@iZbp1d4tisi44j6vxze02fZ tmp]# ./a.outParent [16901] - start a container!Container [1] - inside the container![root@container tmp]# ps -elfF S UIDPIDPPIDC PRINI ADDR SZ WCHANSTIME TTYTIME CMD4 S root100800 - 29185 do_wai 20:04 pts/300:00:00 /bin/bash0 R root3510800 - 38833 -20:05 pts/300:00:00 ps -elf
在通過創(chuàng)建mount 后,父進程會把自己的文件結(jié)構(gòu)復制給子進程中 。而子進程中新的中的所有mount操作都只影響自身的文件系統(tǒng),而不對外界產(chǎn)生任何影響 。這樣可以做到比較嚴格地隔離 。
上面的代碼是在子進程中重新mount了一次,否則還是會看到父進程的proc目錄!
2.5 User
User 主要是用了的參數(shù) 。使用了這個參數(shù)后,內(nèi)部看到的UID和GID已經(jīng)與外部不同了,默認顯示為65534 。那是因為容器找不到其真正的UID所以,設(shè)置上了最大的UID(其設(shè)置定義在/proc/sys//) 。
要把容器中的uid和真實系統(tǒng)的uid給映射在一起,需要修改 /proc// 和 /proc// 這兩個文件 。這兩個文件的格式為: ID–ns ID–ns
其中:
$ cat /proc/2465/uid_map010001
再比如下面的示例:表示把內(nèi)部從0開始的uid映射到外部從0開始的uid , 其最大范圍是無符號32位整形
$ cat /proc/$/uid_map004294967295
User 是以普通用戶運行,但是別的需要root權(quán)限 , 那么,如果我要同時使用多個 , 該怎么辦呢?一般來說,我們先用一般用戶創(chuàng)建User,然后把這個一般用戶映射成root,在容器內(nèi)用root來創(chuàng)建其它的 。
2.6
2.7 文件
同一個容器的進程在一個NS下 。
本文到此結(jié)束,希望對大家有所幫助 。
- linux進程間的通信方式有哪些
- linux學習~巧用setup命令
- 6 每天一個Linux 命令 用戶和用戶組管理
- Linux操作系統(tǒng)與命令詳解
- Linux系統(tǒng)虛擬機和云服務(wù)配置,快速搭建學習環(huán)境
- 文件管理 Linux基礎(chǔ)命令-02
- 一起來學大數(shù)據(jù)|Linux常用管理命令,及大數(shù)據(jù)集群的搭建
- linux基礎(chǔ)20課07,軟件包的安裝與管理 曉桂科技
- Linux查看文本命令大全
- Linux 系統(tǒng) CPU 占用率太高?
