> For the complete documentation index, see [llms.txt](https://okzkx.gitbook.io/blogs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://okzkx.gitbook.io/blogs/game-tech/computer/operating-system/memory/virtual-memory.md).

# virtual-memory\_冲突文件\_zkx\_20240828215908

* [计算机内存体系](https://space.bilibili.com/39521068/channel/collectiondetail?sid=1898345\&spm_id_from=333.788.0.0)

### 虚拟内存

* **虚拟内存地址**（*Virtual Memory Address*）
* **物理内存地址**（*Physical Memory Address*）

### 管理虚拟地址与物理地址之间的关系

#### 内存分段

```
- 内存碎片
- 内存交换把段整体移动填充内存碎片
- 内存交换的效率低
	- 如果内存交换的时候，交换的是一个占内存空间很大的程序，这样整个机器都会显得卡顿。
- 
```

#### 内存分页

```
- **分页是把整个虚拟和物理内存空间切成一段段固定尺寸的大小** 
- 页（Page）。在 Linux 下，每一页的大小为 4KB。
- 虚拟地址与物理地址之间通过**页表**来映射
- 内存管理单元 （MMU）就做将虚拟内存地址转换成物理地址的工作。
- 当进程访问的虚拟地址在页表中查不到时，系统会产生一个缺页异常，进入系统内核空间分配物理内存、更新进程页表，最后再返回用户空间，恢复进程的运行。
- 页与页之间是紧密排列的，所以不会有外部碎片。
- 程序不足一页大小，我们最少只能分配一个页，所以页内会出现内存浪费，所以针对内存分页机制会有内部内存碎片的现象。
```

**页加载**

* 如果内存空间不够，操作系统会把其他正在运行的进程中的「最近没被使用」的内存页面给释放掉
* 只有在程序运行中，需要用到对应虚拟内存页里面的指令和数据时，再加载到物理内存里面去。
* 虚拟地址分为两部分，**页号**和**页内偏移**。页号作为页表的索引，**页表**包含物理页每页所在**物理内存的基地址**
* 需要很大的内存存储页表

**多级页表**

* 把这个 100 多万个「页表项」的单级页表再分页，将页表（一级页表）分为 `1024` 个页表（二级页表），每个表（二级页表）中包含 `1024` 个「页表项」，形成**二级分页**
*

```
![](https://cdn.xiaolincoding.com//mysql/other/19296e249b2240c29f9c52be70f611d5.png)
```

* **如果某个一级页表的页表项没有被用到，也就不需要创建这个页表项对应的二级页表了，即可以在需要时才创建二级页表**。

**TLB**

专门存放程序最常访问的页表项的 Cache，这个 Cache 就是 TLB（*Translation Lookaside Buffer*） ，通常称为页表缓存、转址旁路缓存、快表

#### 段页式内存管理

* 先将程序划分为多个有逻辑意义的段，也就是前面提到的分段机制；
* 接着再把每个段划分为多个页，也就是对分段划分出来的连续空间，再划分固定大小的页；
* 地址结构就由**段号、段内页号和页内位移**三部分组成。
