虚拟内存管理知识点回顾

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/puliao4167/article/details/87867735

概述

    首先需要知道虚拟内存是一个抽象的概念。概念上而言,虚拟内存是一个存放在磁盘上N个连续字节大小的单元组成的数组。每个进程都拥有一个虚拟内存空间,在此空间上进程可以对虚拟内存进行管理和应用(例如内存映射和malloc、free等动态分配内存空间)。虚拟内存的作用(为什么需要虚拟内存?而不是直接操控物理内存):

  1. 将主存可以看成是一个存储在磁盘上地址空间的高速缓存,也就是说,其功能是在主存中自动缓存最近使用的存放在磁盘上的虚拟地址空间中的内容
  2. 为每个进程提供一个一致的地址空间,从而简化内存管理
  3. 保护每个进程的地址空间不被其他进程破坏

虚拟内存作为缓存的工具

    现代计算机采用的是虚拟寻址方式,也就是说,CPU传出来的地址是虚拟地址,这个虚拟地址要转换成物理地址,才能真正在主存中“寻址”,因此就需要一个地址翻译,也就是页表。页表就是将虚拟页映射到物理页,硬件通过读取页表中的页表条目将虚拟地址转换成物理地址。这里就会有一个页命中率的问题。当页表中有这个虚拟地址对应的物理页号时候(命中,页表条目中有效位置1),则接下来可直接去主存(或者高速缓存)的物理地址中取数据;当页表中虚拟地址没有设置有效位(未命中,即缺页),此时就会产生一个缺页异常,调用内核中的缺页处理程序,选择页表中的一个牺牲页调出(如果其更改了则会让其重新写回磁盘),然后将目标页调入内存,同时更新页表,然后异常处理程序返回。然后会重新执行导致缺页的指令,此时即会命中。

    以上两张图分别代表虚拟地址命中和不命中的情况。

虚拟内存作为内存管理工具

    实际上,操作系统为每个进程都提供了一个独立的页表,因为每个进程都有一个独立的虚拟地址空间。多个虚拟页面可以映射到同一个共享物理页面上,即内存共享(进程IPC方法之一)。虚拟内存简化了如下内存管理:

  1. 简化链接。进程虚拟地址空间的一致性极大地简化了连接器的设计和实现,允许连接器生成完全可连接的可执行文件,而这些可执行文件是独立于物理内存中的代码和数据的位置。
  2. 简化加载。虚拟内存使得容易向内存中加载可执行文件和共享对象文件。加载器从不从磁盘到内存复制任何数据,虚拟内存系统会按照运行时候的需求自动掉入数据页。
  3. 简化共享。虚拟内存可以使得进程与进程之间实现代码和数据共享(如共享库,内存公有映射)
  4. 简化内存分配。虚拟内存为用户进程提供了一个简单的分配额外内存的机制(malloc等)

地址翻译过程

    下图所示的是虚拟地址与物理地址通过页表的对应关系以及利用页表的地址翻译过程。从图中可知,MMU利用虚拟页号作为页表中的索引,根据索引才能得到物理页号,而虚拟地址中的虚拟页偏移量则可直接放到物理地址中。

    如果只利用页表进行地址翻译的话,速度较慢,因为要多次访问cache或者主存。因此在CPU的MMU中加上一个快表(TLB),其是一个小的、虚拟寻址的缓存,其每一行都保存着一个由单个PTE组成的块。

扫描二维码关注公众号,回复: 5824333 查看本文章

    下图展示了Core i7的地址翻译过程,从CPU产生虚拟地址的时刻一直到来自内存的数据到达CPU,页表采用的是四级页表层次结构,这样做的好处在于当快表未命中的时候,通过页表查询也能快速找到物理地址,从而到L1 cache中查找数据。

Linux中的虚拟内存系统

    Linux为每个进程维护一个单独的虚拟地址空间,如下图所示。内核虚拟内存包含内核中的代码和数据机构,也包含每个进程都不同的数据(如页表,内核在进程的上下文中执行代码时使用的栈,以及距离虚拟地址空间的各种数据结构)

参考 《csapp》《TLPI》

猜你喜欢

转载自blog.csdn.net/puliao4167/article/details/87867735