> For the complete documentation index, see [llms.txt](https://ryukiedev.gitbook.io/wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ryukiedev.gitbook.io/wiki/ni-xiang/17.-xu-ni-nei-cun.md).

# 17.虚拟内存

### 一、物理内存

早期计算机系统的内存地址都是物理地址。

#### 1.1 内存不够用

应用程序会被完整加载到内存中，大量浪费空间。

![虚拟内存-应用程序完整加载](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MI8JgbGh3U6X_oedqkm%2Fuploads%2Fgit-blob-2a28d19f44f886cbd7d9a88799e2075b252f1a54%2F%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98-%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E5%AE%8C%E6%95%B4%E5%8A%A0%E8%BD%BD.png?alt=media)

#### 1.2 物理地址不安全

可以直接访问内存地址实现跨进程，访问其他应用程序的进程。

![虚拟内存-直接访问物理地址](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MI8JgbGh3U6X_oedqkm%2Fuploads%2Fgit-blob-8bac42d89cc520086cde4f0f124005e6fd57a4f4%2F%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98-%E7%9B%B4%E6%8E%A5%E8%AE%BF%E9%97%AE%E7%89%A9%E7%90%86%E5%9C%B0%E5%9D%80.png?alt=media)

***物理内存中的数据不会清除，只覆写***：这个过程是系统控制的，新的需要存进物理内存的数据，会被写入最不活跃的区域中。应用在后台可能被kill掉的原因之一就是被覆写了。

### 二、虚拟内存

#### 2.1 虚拟页表

应用程序进程内拿到的地址并不是真实的地址，会通过`虚拟页表`映射到物理内存。

> `iOS` 一页数据 `16kb`
>
> `Mac` `4K` ，可以在终端中使用 `PAGESIZE`，命令获取

#### 2.2 内存优化

应用程序不会完整的加载，当用到某一页数据的时候，才会被加载到物理内存中。

![虚拟内存](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MI8JgbGh3U6X_oedqkm%2Fuploads%2Fgit-blob-9b596ffaa9d0d5411bdf2072d6963ef04be3d264%2F%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98-%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98.png?alt=media)

流程：

* 系统和CPU配合进行地址翻译
  * 硬件中MMU（内存管理单元）进行地址翻译
    * 非常快
    * 高速缓存
      * 映射过的会被缓存不会重复翻译
  * 找到物理地址
* 将数据加载进物理内存或读取

#### 2.3 ASLR

`ASLR` 每次启动为 `虚拟页表` 添加随机的偏移值，已获得更高的安全性。

### 三、 缺页中断

由于 `虚拟页表` 的存在，在我们代码访问的数据 `page` 没有被加载进内存的时候，就会出现 `PageFault` `缺页中断`。而大量的缺页中断会影响应用的启动速度。

而我们可以通过 `二进制重排` 对数据在 `MachO` 中的分页布局进行优化，使启动时相关的数据尽量在连续的 `page` 中，来减少 `Page Fault` 的次数。

> 这里我有进行一次相关的实战：[二进制重排实践](/wiki/ios/you-hua/03.-er-jin-zhi-zhong-pai-shi-jian.md)
