研究一下 容器 的 原理
这里 说 的 容器 是 操作系统 层 的 容器, 比如 ixc 、Docker 这种 。
容器, 有 自己 的 硬件资源, 可以 给 每个 容器 分配 指定 的 硬件资源 , 容器 和 容器 之间 是 隔离 的 , 隔离 是指 一个 容器 里 的 应用程序 不能 访问 到 另一个 容器 的 资源 , 容器 和 容器 之间 就像 一个个 独立 的 计算机 和 操作系统 。
对 使用者 来说, 容器 提供 的 接口 和 操作系统 一样, 所以 容器 也是 一个 虚拟操作系统 。
这就是 容器, 可以用 容器 实现 虚拟化, 或者说, 可以 把 容器 当 虚拟机 用 。
了解了 容器 的 功能, 那么, 要 怎么 实现 容器 呢 ?
我 提出 2 个 方案 :
方案一 , 进程组
方案二 , 进程
方案一 是 把 容器 当成 一个 进程组, 方案二 是 把 容器 当成 一个 进程 。
先来 看看 方案一, 上面说到 容器 有 自己 的 硬件资源, 这些 “硬件资源” 不是 直接 的 硬件资源, 而是 经过 操作系统 抽象 的, 比如 虚拟内存, 文件系统 。
虚拟内存 由 内存 和 外存 组成, 文件系统 对应 的 硬件 是 硬盘 、光盘 、U 盘, 文件系统 是 对 硬盘 、光盘 、U 盘 等 外部存储器 的 抽象 。
具体 的 , 容器 的 资源 有 :
1 CPU, 按 占用率 算
2 虚拟内存, 按 存储空间 和 地址空间 算, 存储空间 表示 大小, 地址空间 表示 范围, 地址空间 用于 容器 间 的 隔离
3 文件系统, 每个 容器 有 一个 虚拟 的 文件系统, 比如 每个 容器 有 自己 的 C 盘 、D 盘 、E 盘 ……
4 虚拟 IP, 每个 容器 都有 一个 自己 的 IP, 甚至 可以 有 多个 IP, 这些 IP 都是 虚拟 IP, 是 从 操作系统 的 IP 协议 里 虚拟出来的, 而 操作系统 的 IP 协议 的 底层 是 物理网卡 。 如果 认为 一个 IP 对应 一个 网卡, 那么 也可以 认为 容器 有 一个 或 多个 虚拟网卡 。
设计 容器, 就是 要 设计 怎样 分配 和 隔离 CPU 、虚拟内存 、文件系统 、虚拟 IP 这 4 项 资源 。
在 方案一 里 , 容器 是 一个 进程组, 这些 进程 都是 操作系统 里 的 普通 的 进程, 只要 让 这些 进程 的 CPU 占用率 总和 不超过 分配 的 大小 就可以 。
这 在 操作系统 的 进程调度 里 可以实现 。 就是 在 进程调度 的 时候, 考虑 给 哪个进程 分配时间片 的 时候, 计算 和 判断 一下 容器 里 的 进程 的 CPU 占用率 总和 就可以了 。
这 对 操作系统 的 进程调度 部分 的 代码 稍作修改 就可以 。 也就是 对 操作系统 的 内核代码 稍作修改 就可以 。
2021-08-17 接着写 。
长话短说 。 方案二 进程 的 方式 可能 行不通 。 一个 进程 作为 一个 容器, 则 容器 里 的 进程 就是 “进程 里 的 进程” , 这 需要 容器 把 操作系统 管理进程 的 部分 都实现一遍, 还有 进程 和 操作系统 之间 的 接口 比如 系统调用 等 都要 实现一遍, 这 呵呵 了 。
还是 方案一 进程组 的 方式 好 。
进程组 的 话, 实现 容器 很简单, 就是 把 操作系统 内核代码 改一下, 把 对 容器 (进程组) 的 CPU 使用率 的 管理 加到 进程调度 的 代码 里 ,
内存隔离 也不用做什么, 在 操作系统 里, 不管 进程 是不是 同一个 进程组(容器), 都不允许 访问 其它 进程 的 内存空间, 如果 尝试访问 就是 越界, 抛出异常, 进程 可能 中止 。
也就是, 进程 的 内存 都是 隔离 的, 容器(进程组) 的 内存 自然 的 就是 隔离 的 。
唯一 要 考虑 的 是, 当 发生 越界时, 异常信息 要不要 区分 同一个容器内 的 进程 间 的 越界, 还是 两个 容器 (的 进程) 间 的 越界, 如果 不区分 异常信息, 那 什么都不用做 。
如果 要 区分 异常信息, 那可能要 硬件支持 和 修改 操作系统 内核代码 。 硬件支持 指 存储管理部件 也要支持 在 进程 之上 还有个 “进程组”, 这样 当 越界 抛出 硬件中断 时, 可以知道 是 哪一个 进程组(容器) 的 哪一个 进程 发生了 越界, 以及 越界访问 的 是不是 另一个 进程组(容器) 的 内存空间 。
同时,也要 修改 操作系统 内核代码, 这里 修改 的 内核代码 是 虚拟内存 模块 , 操作系统 对 存储管理部件 设置 页表 时 要 设置 进程组 。 也就是, 本来,操作系统 设置 页表 会 设置 页 和 进程 的 对应关系, 当然 还有 页 和 物理内存页 的 对应关系, 现在, 还要 加上 设置 进程 和 进程组 的 对应关系 。
另一方面, 当 越界时, 存储管理部件 抛出 越界中断, 操作系统 要 读取 引发越界 和 被越界 的 2 个进程组 的 ID 。
但, 就为了 在 越界 的 异常信息 里 知道 是不是 跨容器 的 越界, 要 搞这么多 周折, 这也不至于吧 ?
真正 要 硬件支持 内存隔离 的 应该是 虚拟机 (VMWare, HyperVisor, XGetn, 指令映射, 虚拟指令 ?) , 由此看来, 容器 确实 轻量 很多 。
外部存储器 (硬盘) 的 隔离(划分) 就 更简单了, 把 一个 文件夹(及其 子文件夹) 虚拟为 一个 盘(分区), 就行了 。
这也要 修改 内核代码, 修改的是 文件系统 模块 。
容器 对 计算机(硬件 / 系统) 资源 的 隔离 和 分配 最基本 的 就是 CPU 内存 外存 这 3 样, 现在, 这 3 样 的 隔离 和 分配 都 解决了 。
我刚 看了 本文 开头, 是 4 样, 还有 网卡, 也就是 虚拟 IP , 这个, 就 改一下 网络协议 模块, 也就是 Socket 模块 吧 。
我听 网友 (还是 文章?) 说, 容器 是 共用一个 内核 的 。 看起来, 还真是 。
我 之前 看过 一篇 文章 里 的 一段文字, 有人 跟 Linus 说 , 容器 现在 做的 怎么怎么样了 , Linus 说, 我不管你们什么容器, 我只要 把 我的 内核 做好就好 。
由此看来, 容器 是 在 开源文化 和 开源技术 上, 对 Linux 的 内核 修改 而来 。
如果 操作系统 是 你 写 的, 在 这个 操作系统 里 改 一个 容器 出来 很容易 。 就跟 开发业务系统, 老板 说 “喂 , 商品 能不能分个组 ? 客户 能不能分个组 ? 权限 能不能分个组? 用户 能不能分个组(角色)?” 一样, 差不多了 。
如果很闲, 三五 个 人, 拿来一个 硬件, 为 它 写一个 操作系统 也 很容易 。 什么硬件 ? 比如 单片机, 这 有点老套 , 那就 手机 吧 !
在 这个年代, 手机 很接地气, 拿一个手机, 把 它 当成 一个 裸机, 写一个 程序 启动 它 吧, 把 它 (的 显示屏) 点亮 吧 !
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2019-12-27 二元隐函数 数值求解