# 3.7 虚拟存储器

此部分详见[操作系统部分](https://aye10032.gitbook.io/os/di-san-zhang-nei-cun-guan-li/3.1-fen-ye-cun-chu-xiang-guan-gai-nian)

## 3.7.1 虚拟存储器的基本概念

**页式存储系统**：一个程序（进程）在逻辑上被分为若千个大小相等的“页面”, “页面”大小与“块”的大小相同。每个页面可以<mark style="color:orange;">**离散地**</mark>放入不同的主存块中。

**逻辑地址**：变量、指令等在程序中的相对地址

**物理地址**：实际在主存中存放的地址

**页表**：每一个页表项中记录着逻辑页号和与之对应的主存块号，<mark style="color:orange;">**页表位于主存中**</mark>

## 3.7.2 逻辑地址访问过程

1. 将逻辑地址拆分为<mark style="color:blue;">**页号**</mark>**+**<mark style="color:purple;">**页内地址**</mark>
2. 根据页号查找页表，找到该页存放的<mark style="color:purple;">**主存日块号**</mark>
3. 将主存块号与页内地址拼接，得到要访问数据的物理地址
4. 访问相应的主存块，依照相应的Cache工作原理访问Cache和主存
5. 将逻辑地址拆分为<mark style="color:blue;">**页号**</mark>**+**<mark style="color:purple;">**页内地址**</mark>
6. 根据页号查找页表，找到该页存放的<mark style="color:purple;">**主存块号**</mark>
7. 将主存块号与页内地址拼接，得到要访问数据的物理地址
8. 访问相应的主存块，依据相应的工作原理查找Cache和主存，访问内容

## 3.7.3 快表（TLB）

快表是一种相联存储器，读取速度快。快表中存放的是页表的副本，Cache中存放的是主存块的副本。

引入了快表之后的查询过程：

1. 将逻辑地址拆分为<mark style="color:blue;">**页号**</mark>**+**<mark style="color:purple;">**页内地址**</mark>
2. 根据页号查询TLB
   1. TLB命中
      1. 直接得到该页面的<mark style="color:purple;">**主存块号**</mark>
   2. TLB未命中
      1. 根据页号查找页表，找到该页存放的<mark style="color:purple;">**主存块号**</mark>
      2. 将该页表项复制到TLB
3. 将主存块号与页内地址拼接，得到要访问数据的物理地址
4. 在Cache中查找相应的主存块
   1. Cache命中
      1. 直接从Cache中得到目标数据
   2. Cache未命中
      1. 从主存中访问目标数据
      2. 将主存块复制到Cache中

与Cache类似，快表存满时，也用类似的算法进行替换。

## 3.7.4 虚拟存储器

基于局部性原理，仅将将一部分内容从外存调入内存中。

### 页式虚拟存储器

将程序<mark style="color:orange;">**分页**</mark>，并仅将部分页面调入内存尽心运行。

通过在页表中增加

* 有效位：页面是否被调入内存
* 外存块号：将外存也进行分块，大小与主存块相同，表示该页面存储在外存的位置
* 访问位：用于页面替换算法
* 脏位：表明这个页面是否被修改（是否需要将修改写回外存）

### 段式虚拟存储器

将程序按照不同的功能模块分段（段大小不一），并仅将部分段调入内存运行。

采用段表来存储分段信息，同时主存不再分页。

### 区别

* **交换单位**
  * CPU—cache：字或字节
  * cache—主存：块
  * 虚拟存储（主存—外存）
    * 段页式：页
    * 页式：页
    * 段式：段
* **透明度**
  * 主存—外存
    * 对系统不透明
    * 对应用程序员透明
  * cache—主存
    * 对系统透明
    * 对应用程序员透明

## 3.7.5 常见概念比较（有待扩展）

**页面/页/页框/页帧**：

**块/盘块**：

**页表项大小**：单个页在页表中的大小

**页表项容量**：$页数\*页表项大小$

**计算Cache**：需要统计脏位、有效位、Clock等
