虚拟内存把磁盘当成内存的延伸:程序以为自己有 4 GB,实际只有 1 GB 也行——用到哪一页才读哪一页。
5.2 是【少去磁盘】,这一节换方向:内存不够时,反过来借磁盘用。
一、内存不够用怎么办
多开几个程序,内存很快就不够;而买内存是有上限的,程序和系统又越做越大。 两个笨办法都不好:让程序自己省着用——每个程序都得操心,太累;报错退出——那没法用。 操作系统选的是第三条路:让磁盘来凑。 于是有了虚拟内存——程序看到的那个【内存】,其实有一半是磁盘假装出来的。
二、分页与按需加载
做法是把内存切成固定大小的页(常见 4 KB),程序用到哪一页,才把哪一页读进来。 程序里的地址是【虚拟地址】,要由 CPU 和操作系统一起换算成真实的物理地址。 没被用到的页,就压根不用读进来——所以一个 4 GB 的地址空间,很可能只占了几十 MB 物理内存。 这也顺便解释了程序为什么能【声明很大、用得很少】:声明只是划界线,不是真占地方。
三、物理内存不够了:交换
真到了装不下的时候,操作系统会把暂时用不到的页写回磁盘,腾出位置给要用的页。 这就是交换(换页)。等那些页又要用时,再从磁盘读回来。 代价很明显:读回来是毫秒级的,而内存本来是纳秒级的——一次交换就等于卡了一下。 所以交换能用,但不能常用。
四、好处远不止扩容
虚拟内存的初衷是扩容,但今天它更重要的价值在别处: 每个进程有独立的地址空间——各写各的,谁也串不到谁。 内存受保护——访问不属于自己的页会被挡住,程序崩溃不至于拖垮整台机器。 程序不必知道自己实际有多少内存——同样的可执行文件在 8 GB 和 32 GB 的机器上都能跑。 代价是那张换算表和换页开销;如果内存实在太小、换页太频繁,就会出现【抖动】——机器看起来一直在忙,其实全在换页。
五、动手 Demo:将磁盘当成内存使用的虚拟内存
虚拟内存=把磁盘当成内存的延伸。 程序看到的地址空间可以远大于机器实际装的内存。
space = 4 * 1024 * 1024 * 1024 # 4 GB 地址空间
phys = 1 * 1024 * 1024 * 1024 # 实际只有 1 GB
page = 4 * 1024 # 一页 4 KB
print("地址空间共 %d 页" % (space // page))
print("物理内存共 %d 帧" % (phys // page))
used = 8 * 1024 * 1024 # 一个只用 8 MB 的程序
print("实际载入 %d 页,占 %.2f%%" % (used // page, used * 100.0 / phys))
实跑输出:
--------------------------------------------------------------------
将磁盘当成内存使用的虚拟内存
--------------------------------------------------------------------
**虚拟内存=把磁盘当成内存的延伸。**
程序看到的地址空间,可以远大于机器实际装的内存。
项目 数值
------------------------------------------
32 位进程的地址空间 4 GB
机器实际装的内存 1 GB
一页的大小 4 KB(4096 字节)
地址空间分成多少页 1048576 页
物理内存分成多少帧 262144 帧
一个只用到 8 MB 的程序,真正被读进来的其实只有:
8 MB ÷ 4 KB = 2048 页
只占物理内存的 0.78%
三条要点:
**程序不必一次全搬进来**——用到哪一页才读哪一页(按需分页)
**物理内存不够时,把暂时不用的页写回磁盘**(这就是交换)
**每个进程各有各的地址空间**——谁也别想串门
**于是【内存不够】这件事被糊住了:程序以为自己有 4 GB,**
实际上只有 1 GB,剩下的靠磁盘在那儿临时顶着。
地址空间有 104 万页,物理内存只有 26 万帧——差着 4 倍,全靠按需加载糊住。 一个只用 8 MB 的程序只载入 2048 页,占物理内存 0.78%。
30 秒实验
- 算一算 4 KB 一页的 1 GB 内存,一共能装多少页。
- 想想为什么把页大小定成 4 KB,定成 4 字节或 4 MB 各有什么坏处。
常见误区
- 以为虚拟内存就是【拿硬盘当内存用,所以内存随便写】。它慢得多,只是应急。
- 以为虚拟内存只是扩容。隔离与保护才是它今天最大的价值。
自测三问(点开对答案)
1. 虚拟内存解决了什么问题? —— 物理内存不够时,让程序仍能运行;同时给每个进程独立的地址空间。 2. 按需加载是什么意思? —— 把地址空间分页,程序用到哪一页才把哪一页读进内存。 3. 什么是交换?代价是什么? —— 把暂时不用的页写回磁盘、用时再读回来;代价是磁盘比内存慢百万倍,频繁交换会让机器变慢。- ☐ 下一节(5.4 将内存当成磁盘使用的固态硬盘)
相关笔记
- 提高磁盘访问速度的磁盘缓存 — 另一条思路
- 将内存当成磁盘使用的固态硬盘 — 干脆把磁盘换成不慢的
- 内存的逻辑结构像一幢大楼 — 一维地址换成页号也是同一种换算
- 🖥️ 服务器工作原理 · 索引 — 服务器怎么攒出来的
- ⚙️ 程序是怎样跑起来的 · 索引