1 Namespace是什么?
linux的namespace机制有点类似于数据库中的schema,可以为不同的进程提供各自的命名空间,命名空间互相隔离,进程跑在自己的namespace中资源互相隔离。
docker使用了namespace的机制,将进程隔离在某个namespace中,而在某一个命名空间内的进程可以感知到其他进程的存在,但是对空间外部的进程一无所知。以一种轻量级的方式实现了虚拟化技术。
namespace提供了多种资源的隔离:
Namespace | clone(...flag...) | 所隔离的资源 |
---|---|---|
Cgroup | CLONE_NEWCGROUP | Cgroup 根目录 |
IPC | CLONE_NEWIPC | System V IPC,POSIX 消息队列 |
Network | CLONE_NEWNET | 网络设备、协议栈、端口等 |
Mount | CLONE_NEWNS | 挂载点 |
PID | CLONE_NEWPID | 进程 ID |
User | CLONE_NEWUSER | 用户和组 ID |
UTS | CLONE_NEWUTS | 主机名和域名 |
多种类型的资源隔离可以让我们从文件系统开始,到进程通信、网络通信、用户权限管理、主机管理,一步步的实现各方面资源的隔离,使进程运行在一个虚拟化的环境中。本文讨论的namespace实现针对Linux内核3.8及其以后的版本。
下面我们针对六种命名空间的API做一些实例讲解,亲身体验隔离的实现底层机制。
【文章福利】小编在群文件上传了一些个人觉得比较好得学习书籍、视频资料,有需要的可以进群【977878001】领取!!!额外赠送一份价值699的内核资料包(含视频教程、电子书、实战项目及代码)
内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料
学习直通车(腾讯课堂免费报名):Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈
2 Namespace实战
关于namespace的系统调用主要有三个:
- clone() – 实现线程的系统调用,用来创建一个新的进程,并可以通过设计上述参数达到隔离。
- unshare() – 使某进程脱离某个namespace
- setns() – 把某进程加入到某个namespace
结合一段代码来介绍几个namespace
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#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 mai