1.为什么要用虚拟内存
2.虚拟内存的核心思想是什么
3.虚拟内存的实现
4.虚拟内存的带来的好处
1.为什么要用虚拟内存
我们平常写代码的时候, 根本不需要关心自己的数据具体存在电脑的哪一根内存条中, 不需要写物理内存地址; 但是早期, 程序是直接使用物理内存地址的, 会带来几个大问题:a.不安全一个程序出错(比如写错了地址)可能会覆盖掉另一个程序甚至操作系统的数据, 导致系统奔溃b.不高效所有程序都需要一次性全部加载到内存中才能运行, 如果你的程序很大, 但内存很小, 就根本无法运行c.不隔离程序之间可以互相窥探数据, 没有隐私和安全可言d.地址不统一每次加载程序, 它都需要在不同的物理地址上运行, 编程非常困难
2.虚拟内存的核心思想是什么
虚拟内存为每个进程提供了一个假象: 每个进程都独享一整个巨大的, 连续的内存空间, 这个内存空间就叫做虚拟地址空间; 而这个虚拟的空间, 需要通过一个翻译官来映射到真实的, 有限的物理内存上
通过图书馆的例子理解虚拟内存- 把物理内存想象成图书馆的阅览室, 座位(内存空间)有限- 把硬盘想象成图书馆巨大的书库, 容量很大, 但存取慢- 把进程想象成来看书的学生- 把虚拟内存想象成图书馆给每个学生的座位号清单a.每个学生(进程)都以为自己有一份完整的, 独立的座位清单(4GB虚拟地址空间)b.学生根据清单上的号码(虚拟地址)去找座位c.图书管理员(MMU, 内存管理单元, CPU里的硬件)负责查看这个清单, 将它翻译成真实的阅览室座位号(物理地址)d.如果学生要看的书(数据)在阅览室(内存)里, 管理员就直接告诉他座位在哪e.如果书不在阅览室(内存不足), 管理员就会从书库(硬盘)将需要的书调出来, 放到一个空座位上, 然后更新清单(页表), 再告诉学生座位号(页面置换)这个过程对学生(进程)是透明的, 他永远只关心清单上的号码(虚拟地址), 而不关心书具体在哪个物理位置
3.虚拟内存的实现
1).分页机制- 物理内存和虚拟空间都被分割成一个个固定大小的块- 物理内存的块叫页框- 虚拟内存的块叫页- 大小通常为4KB- 这样, 管理内存就变了管理一页一页的数据2).页表a.页表就是翻译清单b.它是每个进程独有的一个数据结构, 存储在内存中; 它的每一行(一个页表项)记录了- 虚拟页号 -> 物理页框号的映射关系- 还有其他重要的标志位存在位: 最重要的一位, 表示这一页数据是在内存中(1)还是在硬盘上(0)修改位: 表示这页数据是否被写过, 如果被修改过, 在换出时就需要写回硬盘权限位: 表示这页是可读, 可写还是可执行3).地址转换当程序读写一个虚拟地址时, CPU里的MMU(内存管理单元)会自动完成以下工作:a.从虚拟地址中分解出虚拟页号和页内偏移量b.用虚拟页号作为索引, 去查当前进程的页表, 找到对应的页表项c.检查页表项的存在位和权限位, 如果权限不对(比如试图写一个只读页), 就会触发异常d.如果存在位是1(页在内存中), 就取出物理页框号e.将物理页框号 + 页内偏移量, 就得到了最终的物理地址, 然后去访问它(这是一个简化的流程, 现代CPU还有TLB快表来加速查询)4).缺页中断如果MMU在查页表时, 发现存在位是0, 说明你要访问的数据不在物理内存中, 还在硬盘上a.CPU会立即触发一个缺页中断b.操作系统内核的中断处理程序会接管CPUc.操作系统会- 在硬盘(交换空间)上找到所需要的页面- 在物理内存里找一个空闲的页框, 如果找不到, 就要根据某种页面置换算法淘汰一个旧的页面- 如果被淘汰的页面被修改过(脏页), 就把它写回硬盘- 然后把需要的页面从硬盘读入到刚才找到的空闲页框中- 更新页表, 将这一页的映射关系改位新的物理页框号, 并把存在位置1d.最后, 中断返回, 重新执行那条导致缺页的指令; 这次再查页表, 就能找到了
4.虚拟内存的带来的好处
a.内存保护每个进程有自己的地址空间, 一个进程崩溃不会影响其它进程, 页表的权限位可以防止代码乱写乱读b.进程隔离进程A无法直接访问进程B的数据, 保证了安全和隐私c.简化编程程序员看到的是统一的、连续的虚拟地址空间, 不用关心物理内存的细节。d.更高的内存利用率允许运行比物理内存更大的程序, 这就是虚拟内存最神奇的地方; 程序只需要把当前最需要的数据(工作集) 放在内存里, 其他不常用的部分可以暂时放在硬盘上, 这就是"用磁盘空间扩展内存"说法的来源e.共享内存通过让不同进程的页表项指向同一个物理页框, 可以实现进程间的共享内存(例如共享库代码)