因为不管存储器多大,程序都可以将其填满。所以 在现代计算机操作系统中 我们设计了 分层存储器体系
在 分层存储器体系中,存在 MB 的快速、昂贵、易失性的高速缓存,GB的速度价格适中的同样易失的内存 ,以及 TB的低速、廉价、非易失的磁盘存储。
操作系统的工作之一 就是 将层次存储系统体系 抽象成为一个 有用的模型 并管理这个抽象。
探索 内存抽象方案:
无存储器抽象
最简单的存储器抽象 即 没有抽象。 早期的大型机、小型计算机 都没有存储抽象。 每一个程序 都直接访问物理内存。
因此 那时候呈现给编程人员的存储器 即是: 从0到某个上限的地址集合,每个地址 对应一个 可容纳 一定数目(通常是 8位)的二进制数据。
指令 Move Register1, 100 即:将 100的物理内存的内容,复制到 register1中。
该种方案下,系统中同时运行两个程序是不可能的。如果进程 A在 地址 100位置写入数据,进程 2 在稍后的时间中 对地址 100进行了改写,可能导致 进程A的崩溃。
但 无内存抽象模式依然广泛存在于嵌入式系统中。比如 洗衣机、微波炉 此类设备 都已经完全被ROM形式的软件控制。 这种情况下,软件都采用 绝对地址寻址的方式,因为 所有运行的程序 都可以被事先确定, 用户不需要运行自己的软件。
问题: 如何在没有存储器抽象的情况下 同时运行多个程序?
操作系统 只需要 把当前的内存中的内容 保存到磁盘上 ,然后将下一个程序 读入到内存中 再次运行即可。 只要在同一时刻 内存中只有一个程序 即可。
历史中 IBM 360 的做法:
- 内存被划分为 大小2KB的块。
- 每个块 分配一个 4位的保护键, 保护键 存储在cpu PSW中的特殊寄存器中。
- 所以: 一个运行中的进程如果访问保护码 与 PSW中的不同的内存,硬件将会捕获该事件。 因为只有系统可以修改保护键,这样就可以 防止 用户进程 之间、用户和操作系统之间的相互干扰。
- 静态重定位技术: 即便 存在保护键,依然无法解决 两个进程 使用重复的绝对地址的问题,我们希望每个进程使用一套自己私有的内存地址来进行内存访问。
IBM 360 采用的方法 即:在第二个 程序 装载到内存 100地址时, 常数100将被 加到 程序的每一个 程序地址上。
存储器抽象: 地址空间
直接暴露物理地址的问题: 1) 用户程序可以简单的寻址内存地址,很容易地破坏 操作系统。 2) 同时运行多个程序将非常困难。
要多个应用程序 同时处于内存 而不互相影响 需要解决两个问题: 1)保护 2)重定位
IBM 360的办法 实际效果并不好,因为 其 静态重定位 技术,不仅缓慢,还需要 额外的标记 来确定 哪些地址 需要被加。(比如 相对地址指令并不需要 + 程序的起始位置
动态重定位: (初步简单实现) 给cpu配置两个寄存器: 基址寄存器 、界限寄存器。 使程序装载期间无需重定位。 此方法可以简单实现存储器抽象。
具体做法:
- 当一个进程运行时 程序的起始地址装载到基址寄存器中,程序的长度 装载到 界限寄存器中。
- 每次 进程访问内存,取一条指令、读写一个内存地址时:
读写地址 --> 地址 + 基址寄存器 --> 检查 是否在 界限寄存器范围内 --> 发送到 内存总线
cpu硬件会将 地址发送到内存总线 之前, 自动把基址寄存器的数值 + 进程发出的地址上。 同时检查结果是否在界限寄存器范围内。 超过了界限则捕获错误。
问题: 上述方法完美的解决了 地址空间抽象 需要的 保护 与 重定位 问题。但是依然存在另外一个 问题,即:程序需要的内存 >> 实际物理内存, 又如何解决呢?
答案是: 交换技术 与 分页 技术
我们先看交换技术:
交换技术:(最简单的策略)
- 将进程完整的调入内存中,多个进程同时运行。
-
当前内存不能满足新进程的内存需要时候,将空闲进程 换出到磁盘中, 通过对进程 内存到磁盘 的换入换出 操作,来实现 同时运行多个进程。