你必须了解Linux的命名空间

发布时间 - 2022-01-25 00:00:00    点击率:

本篇文章给大家带来了关于linux命名空间的相关知识,命名空间提供了虚拟化的一种轻量级形式,使得我们可以从不同的方面来查看运行系统的全局属性,希望对大家有帮助。

一、基本概念

  命名空间(Linux namespace)是linux内核针对实现容器虚拟化映入的一个特性。我们创建的每个容器都有自己的命名空间,运行在其中的应用都像是在独立的操作系统中运行一样,命名空间保证了容器之间互不影响。

  Linux的命名空间机制提供了一种资源隔离的解决方案。PID,IPC,Network等系统资源不再是全局性的,而是属于特定的Namespace。Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。

  传统上,在Linux以及其他衍生的UNIX变体中,许多资源是全局管理的。例如,系统中的所有进程按照惯例是通过PID标识的,这意味着内核必须管理一个全局的PID列表。而且,所有调用者通过uname系统调用返回的系统相关信息(包括系统名称和有关内核的一些信息)都是相同的。用户ID的管理方式类似,即各个用户是通过一个全局唯一的UID号标识。

  全局ID使得内核可以有选择地允许或拒绝某些特权。虽然UID为0的root用户基本上允许做任何事,但其他用户ID则会受到限制。例如UID为n的用户,不允许杀死属于用户m的进程( m≠ n)。但这不能防止用户看到彼此,即用户n可以看到另一个用户m也在计算机上活动。只要用户只能操纵他们自己的进程,这就没什么问题,因为没有理由不允许用户看到其他用户的进程。

  但有些情况下,这种效果可能是不想要的。如果提供Web主机的供应商打算向用户提供Linux计算机的全部访问权限,包括root权限在内。传统上,这需要为每个用户准备一台计算机,代价太高。使用KVM或VMWare提供的虚拟化环境是一种解决问题的方法,但资源分配做得不是非常好。计算机的各个用户都需要一个独立的内核,以及一份完全安装好的配套的用户层应用。

  命名空间提供了一种不同的解决方案,所需资源较少。在虚拟化的系统中,一台物理计算机可以运行多个内核,可能是并行的多个不同的操作系统。而命名空间则只使用一个内核在一台物理计算机上运作,前述的所有全局资源都通过命名空间抽象起来。这使得可以将一组进程放置到容器中,各个容器彼此隔离。隔离可以使容器的成员与其他容器毫无关系。但也可以通过允许容器进行一定的共享,来降低容器之间的分隔。例如,容器可以设置为使用自身的PID集合,但仍然与其他容器共享部分文件系统。

二、实现

  命名空间的实现需要两个部分:每个子系统的命名空间结构,将此前所有的全局组件包装到命名空间中;将给定进程关联到所属各个命名空间的机制。

  子系统此前的全局属性现在封装到命名空间中,每个进程关联到一个选定的命名空间。每个可以感知命名空间的内核子系统都必须提供一个数据结构,将所有通过命名空间形式提供的对象集中起来。 struct nsproxy用于汇集指向特定于子系统的命名空间包装器的指针。在文件nsproxy.h中有:

/*
 * A structure to contain pointers to all per-process
 * namespaces - fs (mount), uts, network, sysvipc, etc.
 *
 * The pid namespace is an exception -- it's accessed using
 * task_active_pid_ns.  The pid namespace here is the
 * namespace that children will use.
 *
 * 'count' is the number of tasks holding a reference.
 * The count for each namespace, then, will be the number
 * of nsproxies pointing to it, not the number of tasks.
 *
 * The nsproxy is shared by tasks which share all namespaces.
 * As soon as a single namespace is cloned or unshared, the
 * nsproxy is copied.
 */struct nsproxy {
	atomic_t count;
	struct uts_namespace *uts_ns;
	struct ipc_namespace *ipc_ns;
	struct mnt_namespace *mnt_ns;
	struct pid_namespace *pid_ns_for_children;
	struct net 	     *net_ns;
	struct time_namespace *time_ns;
	struct time_namespace *time_ns_for_children;
	struct cgroup_namespace *cgroup_ns;};

  当前内核的以下范围可以感知到命名空间

  1、 UTS命名空间包含了运行内核的名称、版本、底层体系结构类型等信息。 UTS是UNIXTimesharing System的简称。

  2、保存在struct ipc_namespace中的所有与进程间通信( IPC)有关的信息。

  3、 已经装载的文件系统的视图,在struct mnt_namespace中给出。

  4、 有关进程ID的信息,由struct pid_namespace提供。

  5、 struct user_namespace保存的用于限制每个用户资源使用的信息。

  6、struct net_ns包含所有网络相关的命名空间参数。

  当我讨论相应的子系统时,会介绍各个命名空间容器的内容。在由于在创建新进程时可使用fork建立一个新的命名空间,因此必须提供控制该行为的适当的标志。每个命名空间都有一个对应的标志,在sched.h文件内:

#define CLONE_NEWCGROUP		0x02000000	/* New cgroup namespace */
#define CLONE_NEWUTS		0x04000000	/* New utsname namespace */
#define CLONE_NEWIPC		0x08000000	/* New ipc namespace */
#define CLONE_NEWUSER		0x10000000	/* New user namespace */
#define CLONE_NEWPID		0x20000000	/* New pid namespace */
#define CLONE_NEWNET		0x40000000	/* New network namespace */

  不同类型的命名空间的作用:

  IPC:用于隔离进程间通讯所需的资源( System V IPC, POSIX message queues),PID命名空间和IPC命名空间可以组合起来用,同一个IPC名字空间内的进程可以彼此看见,允许进行交互,不同空间进程无法交互

  Network:Network Namespace为进程提供了一个完全独立的网络协议栈的视图。包括网络设备接口,IPv4和IPv6协议栈,IP路由表,防火墙规则,sockets等等。一个Network Namespace提供了一份独立的网络环境,就跟一个独立的系统一样。

  Mount:每个进程都存在于一个mount Namespace里面,  mount Namespace为进程提供了一个文件层次视图。如果不设定这个flag,子进程和父进程将共享一个mount Namespace,其后子进程调用mount或umount将会影响到所有该Namespace内的进程。如果子进程在一个独立的mount Namespace里面,就可以调用mount或umount建立一份新的文件层次视图。

  PID::linux通过命名空间管理进程号,同一个进程,在不同的命名空间进程号不同!进程命名空间是一个父子结构,子空间对于父空间可见。

  User:用于隔离用户

  UTS:用于隔离主机名

  每个进程都关联到自身的命名空间视图,在任务定义的结构体task_struct中有如下定义:

struct task_struct {.../* 命名空间 */struct nsproxy *nsproxy;...}

  因为使用了指针,多个进程可以共享一组子命名空间。这样,修改给定的命名空间,对所有属于该命名空间的进程都是可见的。
  init_nsproxy定义了初始的全局命名空间,其中维护了指向各子系统初始的命名空间对象的指针。在kernel/nsproxy.c文件内有

struct nsproxy init_nsproxy = {
	.count			= ATOMIC_INIT(1),
	.uts_ns			= &init_uts_ns,#if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
	.ipc_ns			= &init_ipc_ns,#endif
	.mnt_ns			= NULL,
	.pid_ns_for_children	= &init_pid_ns,#ifdef CONFIG_NET
	.net_ns			= &init_net,#endif#ifdef CONFIG_CGROUPS
	.cgroup_ns		= &init_cgroup_ns,#endif#ifdef CONFIG_TIME_NS
	.time_ns		= &init_time_ns,
	.time_ns_for_children	= &init_time_ns,#endif};

三、UTS命名空间

  UTS命名空间几乎不需要特别的处理,因为它只需要简单量,没有层次组织。所有相关信息都汇集到下列结构的一个实例中。在utsname.h文件内:

struct uts_namespace {
	struct new_utsname name;
	struct user_namespace *user_ns;
	struct ucounts *ucounts;
	struct ns_common ns;} __randomize_layout;

  uts_namespace所提供的属性信息本身包含在struct new_utsname中:

struct oldold_utsname {
	char sysname[9];
	char nodename[9];
	char release[9];
	char version[9];
	char machine[9];};#define __NEW_UTS_LEN 64struct old_utsname {
	char sysname[65];
	char nodename[65];
	char release[65];
	char version[65];
	char machine[65];};struct new_utsname {
	char sysname[__NEW_UTS_LEN + 1];
	char nodename[__NEW_UTS_LEN + 1];
	char release[__NEW_UTS_LEN + 1];
	char version[__NEW_UTS_LEN + 1];
	char machine[__NEW_UTS_LEN + 1];
	char domainname[__NEW_UTS_LEN + 1];}

  各个字符串分别存储了系统的名称( Linux…)、内核发布版本、机器名,等等。使用uname工具可以取得这些属性的当前值,也可以在/proc/sys/kernel/中看到

z@z-virtual-machine:~$ cat /proc/sys/kernel/ostype
Linux
z@z-virtual-machine:~$ cat /proc/sys/kernel/osrelease5.3.0-40-generic

  初始设置保存在init_uts_ns中,在init/version.c文件内:

struct uts_namespace init_uts_ns = {
	.ns.count = REFCOUNT_INIT(2),
	.name = {
		.sysname	= UTS_SYSNAME,
		.nodename	= UTS_NODENAME,
		.release	= UTS_RELEASE,
		.version	= UTS_VERSION,
		.machine	= UTS_MACHINE,
		.domainname	= UTS_DOMAINNAME,
	},
	.user_ns = &init_user_ns,
	.ns.inum = PROC_UTS_INIT_INO,#ifdef CONFIG_UTS_NS
	.ns.ops = &utsns_operations,#endif};

相关推荐:《Linux视频教程》


# linux  # 命名空间  # 封装  # 字符串  # 结构体  # 指针  # 数据结构  # 接口  #   # Struct  # Namespace  # 对象  # unix  # 虚拟化  # 多个  # 一台  # 自己的  # 都是  # 都有  # 中有  # 系统资源  # 所需  # 相关信息  # 机上 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  如何在IIS7上新建站点并设置安全权限?  Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)  Laravel如何实现RSS订阅源功能_Laravel动态生成网站XML格式订阅内容【教程】  制作企业网站建设方案,怎样建设一个公司网站?  Laravel怎么在Blade中安全地输出原始HTML内容  Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  Laravel Docker环境搭建教程_Laravel Sail使用指南  浏览器如何快速切换搜索引擎_在地址栏使用不同搜索引擎【搜索】  作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】  猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】  Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面  Win11怎么设置默认图片查看器_Windows11照片应用关联设置  如何彻底卸载建站之星软件?  如何在云指建站中生成FTP站点?  香港服务器网站卡顿?如何解决网络延迟与负载问题?  bootstrap日历插件datetimepicker使用方法  如何用免费手机建站系统零基础打造专业网站?  Laravel如何实现API版本控制_Laravel版本化API设计方案  Laravel如何实现事件和监听器?(Event & Listener实战)  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  如何在自有机房高效搭建专业网站?  如何在Ubuntu系统下快速搭建WordPress个人网站?  Laravel如何自定义错误页面(404, 500)?(代码示例)  Laravel如何实现用户密码重置功能?(完整流程代码)  非常酷的网站设计制作软件,酷培ai教育官方网站?  安克发布新款氮化镓充电宝:体积缩小 30%,支持 200W 输出  详解Oracle修改字段类型方法总结  高端云建站费用究竟需要多少预算?  Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  linux写shell需要注意的问题(必看)  rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted  桂林网站制作公司有哪些,桂林马拉松怎么报名?  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  Laravel中的Facade(门面)到底是什么原理  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  深入理解Android中的xmlns:tools属性  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  JavaScript如何实现路由_前端路由原理是什么  移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?  如何在阿里云香港服务器快速搭建网站?  使用Dockerfile构建java web环境  Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧  Laravel项目如何进行性能优化_Laravel应用性能分析与优化技巧大全  Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程  Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置