设计 一个 CPU 的 存储管理部件

设计 一个  CPU 的 存储管理部件,    这个 题 留给 大家 思考  。

 

 

CPU 里 有 存储管理部件,   据说 以前 是 在 北桥 芯片 里  。

 

存储管理部件 的 功能 是 地址映射(页映射),   判断 对 内存 的 访问 是否 越界  。

 

对 内存 的 访问 越界 就是 一个 进程 的 代码 访问 了 另一个 进程 的 内存 ,      这是 不允许 的  。

 

但 有些时候,   操作系统 允许 多个 进程 之间 共享 一块 内存,    比如 管道,  或者 共享内存  。    这 通常 用于 进程间 通信  或  传输数据  。

 

共享内存 允许 共享 这块 内存 的 多个 进程 访问,    存储管理部件 应该 也要 支持 这个 功能  。

 

实际上,    一级 Cache 有 自己 的 存储管理部件 ,    二级 Cache 有 自己 的 存储管理部件 ,    三级 Cache 有 自己 的 存储管理部件 ,    虚拟内存 有 自己 的 存储管理部件   。

 

这里 的  一级 Cache  二级 Cache  三级 Cache   是  CPU 的 一级 Cache  二级 Cache  三级 Cache  。   虚拟内存 是 操作系统 的 虚拟内存  。

 

 

具体的 ,

 

一级 Cache 的 存储管理部件  的 功能 是  一级 Cache 和 虚拟内存 之间 的 地址映射(页映射),   以及 防止 内存 的 越界访问  。

二级 Cache 的 存储管理部件  的 功能 是  二级 Cache 和 虚拟内存 之间 的 地址映射(页映射),   以及 防止 内存 的 越界访问  。

三级 Cache 的 存储管理部件  的 功能 是  三级 Cache 和 虚拟内存 之间 的 地址映射(页映射),   以及 防止 内存 的 越界访问  。

虚拟内存 的 存储管理部件  的 功能 是    内存 和 虚拟内存 之间 的 地址映射(页映射),   以及 防止 内存 的 越界访问  。

 

每个 存储管理部件  都  维护 一份 页表  。

硬件上,    一级 Cache 的 存储管理部件  应该 在 一级 Cache 的 附近,   访问 一级 Cache 的 存储管理部件 和 访问 一级 Cache  一样快  。

 

其实 还有一个 页表,   维护  页 在 页文件 里 的 位置  。    这个 页表 称为 页文件页表  。

虚拟内存 将  常用 的 数据 保存 在 内存 里 ,   不常用 的 数据 保存 在 硬盘 的 一个 文件 里,    这个 文件 就是 页文件  。   

 

要 加载 一个 页 到 内存 时,  需要 知道 页 在 页文件 里 的 位置  。    页 可能 创建 、销毁,    为了 避免 页文件 无限扩大,   会 “重复利用”  页文件 的 空间 来 保存 页,  所以,  页文件页表 会 经常 添加 删除 插入 页表项,    而 查找 页文件页表 的 工作  可以 用 软件 的 方式 来 做  。   可以用 红黑树 二分法 来 做  。

 

但 按理,    页文件页表 也可以用 硬件 的 存储管理部件 来  实现,  再 增加 一个 存储管理部件 就可以  。  但 问题 是,   在 64 位 架构 下,   64 位 地址 有  4G * 4G = 16 EB  的  地址空间,    16 EB 除以 页 的 大小 就是 可能 的 页 的 数量,    这个 数量 是 很大 的,     虽然 实际 中 并不会 用到 那么 大,  但在 64 位 架构 下,   单个 进程 的 虚拟内存 确实 可以 申请 超过  4G ,   比如 几十 G ,    甚至 上百 G 应该 也可能  。

 

总的来说,    页 的 数量 很多,      如果 要 用 硬件 的 存储管理部件 来 保存 页表 的 话,    需要 很大 的 存储空间,   这个 可能 不现实   。

 

但 反过来 再想一下,    如果 有 1M  个页 ,  也就是 100 万 个 页,     够用了吧  ?              假设 一个 页 的 大小 是  4 KB,     1M 个 页 的 空间是 1M * 4 KB = 4 GB ,

 

如果  10 M 个 页,   空间 是  40 GB,     100 M 个 页 ,  空间 是 400 GB,   如果 把  页 弄大 一点,  比如 16 KB,    那么 100 M 个 页 的 空间 是  1.6 TB   。

 

把   100 M 个 存储单元  做到 硬件 里 ,     按现在 的 技术来说,  好像 很平常   。    当然 这里 的 存储单元 比 一个 Byte 大,   应该是 一个 页表项 的 大小,    当然,   每个 页表项 可能 会 有 相应 的 一些 逻辑电路 用于 查找 页表项 和 判断 内存访问 是否 越界   。

 

但 因为 查找页表项 和 判断 内存访问 越界 的 逻辑电路 可能 是 每个页表项 都 会 有,    一个 页表项 对应 一个 页,    所以 当 页 的 数量 很大 时,   电路 体量 可能 很庞大   。

 

我 估计,    传统上,    到 目前为止,    页文件页表 的 管理 可能 是 由 软件 的 方式 实现 的,   即 由 操作系统 实现,  而不是 硬件 的 存储管理部件  。

 

在 内存 划出 一段 空间,  将 页表项  保存在 这段 内存 里 ,   保存不下 的,    存入 页文件,  要用 的 时候,  再从 页文件 加载 到 内存,   这样,  只要 页文件 够大,  页文件页表  可以  持续 扩展  。     

 

而 实际上,     保存不下 的 页表项 存入 页文件,  要用 的 时候,  再从 页文件 加载 到 内存,   这个 和 虚拟内存 类似,    可以 同样 用 虚拟内存 来 管理,    这是  “自己 管理 自己”    。

 

既然 统一 纳入 虚拟内存 管理,    那么  “在 内存 划出 一段 空间,  将 页表项  保存在 这段 内存 里”  ,    保存 页表项 的 这段 内存空间 也可以 不是 固定 的 ,    统一 由 虚拟内存 管理  就好  。

 

总之,    这是  “自己 管理 自己”    。      这样 的  程序 是 可以 设计 出来 的   。

 

其实,   这跟 内存堆 的 管理 类似,  甚至 一样  。           这个 管理逻辑 是 很啰嗦 很麻烦 的  。

 

 

刚才 说远了  。

 

把  存储管理部件 搞清楚了,    CPU 架构 也差不多 清楚了   。

 

 

把  逻辑电路 原理 搞清楚了,     复杂指令集 (CISC) 、微指令 、“流水” 架构 什么 的 ,   也 都是 浮云  。

 

无非 就是 在 一个 时钟周期 尽量 执行 多个 逻辑运算 ,   对于 需要 多个 时钟周期 才能 完成 的 指令功能,  协调安排 好 各个 逻辑运算,   使之 尽量 并行协作,  在 尽可能少 的 时钟周期 里 完成 指令功能  。

 

在 一个 时钟周期 里 尽量 执行 多个 逻辑运算,    这需要 固化 这些 逻辑运算 和 调度 这些 逻辑运算 的 逻辑运算 到 电路 里 ,    电路 会 膨胀,  但 执行速度 会 变快  。

 

 

所以,  把 这些 搞清楚了,   画出 CPU 的 架构图 和 逻辑电路图  也很简单  。

 

但是,   当 电路 的 规模 很大 时,   要 计算出 电路参数 使得 电路 稳定运行,    这 并不简单,    需要 一些 工夫  。

 

当 电路 规模 很大 时,    在 硬件工艺 上,   要 把 电路 集成 到 很小 的 一块 硅片 上,   这 也不简单,   也需要 工夫  。

 

 

CPU 本身 也是 一个 计算机系统,   只不过  集成电路 和 “纳米工艺”  让 它  微观化 了,    而 我们 又 习惯于 用 高级 的 抽象 来 使用 计算机, 高级 的 抽象 比如 操作系统 、编程语言 、软件 ,   所以,    CPU 也 变得 复杂神秘深奥 起来 了  。

 

 

其实  本文 说 的 这些,   大部分 都是 我 猜 的 ,  或者说 推测 的  。

 

但 不管 怎么说,       把  存储管理部件 搞清楚了,    CPU 架构 也差不多 清楚了   。

 

所以呢,     设计 一个  CPU 的 存储管理部件,    这个 题 留给 大家 思考 吧,   哈哈  。

 

 

 

 

 

原文地址:https://www.cnblogs.com/KSongKing/p/14197798.html