总结--虚拟内存

前言

本文为学习虚拟内存时的学习总结。如有错误,欢迎指正。

正文

源代码经过编译和链接后会生成一个可执行目标文件,这里再次贴出这个可执行目标文件的结构图:

详情见:总结--链接器的工作原理

我们的关注点聚集在代码段和数据段中。这张图和上篇文章相比虽然结构一致,但是却多了一个0x400000标志。这个标志的意思是代码段地址总是从0x400000固定位置开始。比如说程序第一条指令cpu寻址的地址应当是0x400000,第二条为0x400001,依次递增。每个程序都是如此。这个地址就是我们所说的虚拟地址。他与可执行目标文件存储在哪无关,是计算机中的一个抽象概念。比如64位的操作系统,那么每个程序都拥有一个完整的0-2^64-1的完整虚拟地址。

页表

cpu如何将虚拟地址映射到真实地址的呢?计算机将虚拟地址等分成固定大小的页(比如说64KB),每个页由一个页条目表示,从而形成一个页表, 我们以程序加载为例:

如图所示,加载器修改页表的信息,将虚拟地址的页与磁盘页通过页条目关联起来。当cpu寻址0x400000时,会通过hash直接定位到对应的页条目,这时取出标志位为0(表明该页存在物理磁盘上,未缓存),会发生一个缺页异常,cpu发生中断告诉操作系统:"小伙子,这个页不存在,赶紧给我调到主存"。这时操作系统缺页调度程序将该页从磁盘调度到主存,将页条目指针指向主存地址,并修改页条目的标志为1(表示已缓存)。此后cpu再次执行寻址0x400000指令,便能从主存成功取出指令。如下图:

通过这样的一个模型,大大减轻了加载器的工作压力。加载也变成了一个看似很轻松的工作。这样子的模型看似可以良好的运行,可是却难免会遇到一个情况,假设我们现在仅有4G主存,而且假设4G空间都被占用了。现在一个程序申请4KB的空间,怎么办?计算机可能会想:"哦豁!完犊子,没空间了,直接报异常吧!"。通常情况还有另外一种解决办法,操作系统允许在磁盘上配置一定空间拓展主存(称为虚拟主存),这时操作系统会在主存中挑选一个或多个页调出主存,存储到虚拟主存中,修改对应的页表条目将其状态置为未缓存,并修改指针指向对应的磁盘地址。当程序再访问到这个页时再从磁盘调入主存。

  • 通过这样的一种模型,每个进程都拥有一个自己完全独立的地址空间,大大简化了多进程申请内存时地址分配的复杂性。
  • 通过这样一种模型,主存充当了磁盘的缓存,这也许跟我们之前讨论的L1,L2高速缓存有点类似。但是他们存在一个很大的不同,高速缓存与主存的缓存块是根据地址来映射的,他们之间的对于关系非常绝对,处理缓存冲突也是十分绝对的将冲突的块刷新回主存。但是虚拟内存的虚拟页在主存和磁盘中的映射关系并不是根据地址一一对应的,他是由一个额外的页表来维护。也就是说仅当主存占满后才会出现空间分配不足的,并且处理这种情况也不是绝对的选取一个映射页调出主存,确定调出那个页取决于操作系统的页面调度算法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值