Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

按需加载与交换空间

复习

  • TLB:给频繁的地址转换加一层缓存
  • 多级页表:页表本身太大时如何按需展开
  • 缺页异常:访问的页面不在内存时 CPU 和内核怎样配合

TL;DR

  • 按需加载:只把眼下需要的页放进内存,其余留在磁盘
  • 磁盘上留出一块交换空间,专门存放暂时不用的页
  • 内存紧张时,把一些页换出到交换空间,需要时再换入
  • 靠这一进一出,程序才能“用着比实际内存更大的空间”

正文

  上一章的缺页异常,已经暗示了一件事:页可以不在内存。这一章把这个思路讲透:内存里只放需要的页,其余的留在磁盘上。

为什么可以“偷懒”

  启动一个程序时,真的需要把它的所有代码和数据都读进内存吗?

  大多数情况下并不需要。程序里很多代码只在特定分支才会执行,很多数据可能整场运行都用不到。如果一开始就全部加载,既慢又占地方。

  于是有了按需加载(demand loading):一开始只装入必要的一部分,其余等真正访问到时,再靠缺页异常一页一页地补进来。用到才给,不用就不给。

交换空间

  可内存总有装满的时候。要腾地方,就得有地方存放被请出去、又没被删掉的页。这个“仓库”,就是磁盘上的一块交换空间(swap space)。

  • 换出(swap out):把暂时不用的页,从内存写到交换空间
  • 换入(swap in):等再次用到它时,从交换空间读回内存
物理内存                交换空间(磁盘)
┌────────┐             ┌────────┐
│ 常用页  │  ←换入/换出→ │ 冷门页  │
└────────┘             └────────┘

一个宏大的错觉

  把“按需加载”和“交换”合在一起看,效果就出来了:

  • 进程的地址空间可以比实际物理内存大得多
  • 内存里只留正在用的那部分,冷的页放去交换空间
  • 需要时再换回来,程序几乎察觉不到

  于是程序真的会“以为”自己拥有一大片内存,而机器只有那么点物理内存——这个虚拟内存的错觉,到这里才算完整。

  不过,内存满了到底该把哪一页请出去?随便挑可不行,选不好会让程序频繁缺页、越跑越慢。下一章,我们专门讨论“换出谁”的问题。

思考题

  交换空间在磁盘上,磁盘比内存慢成千上万倍。既然换入换出这么慢,为什么虚拟内存还能让程序跑得动?

小结

知识点

  • 按需加载:用到才把页读进内存
  • 交换空间:磁盘上存放暂时不用的页
  • 换出与换入
  • 让程序可用空间大于物理内存

参考资料

  1. Wikipedia(zh):虚拟内存:按需分页与交换
  2. Wikipedia(zh):交换空间:swap

思考题答案(仅供参考)

  因为程序访问内存有局部性:在一段时间里,它反复用到的只是少数页。这些“热”页留在内存里,绝大多数访问根本碰不到交换空间,速度不受影响;只有偶尔访问到“冷”页时,才需要从磁盘换入,慢那么一下。换句话说,交换是“兜底”,局部性让这个兜底很少被触发。相反,如果程序毫无局部性、频繁触碰大量页,就会不停换入换出,慢到无法忍受——这正是下一章“内存抖动”要讲的。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪