Skip to content

Latest commit

 

History

History
73 lines (39 loc) · 6.14 KB

vm.md

File metadata and controls

73 lines (39 loc) · 6.14 KB

虚拟内存

一个进程是与其他进程共享CPU与主存资源的,但共享主存会形成一种挑战。现代系统提供了一种对主存的抽象概念,叫做虚拟内存(VM)。它为每一个进程提供了一个大的、一致的和私有的地址空间。

  • 将主存看成是存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据。
  • 为每个进程提供了一致的地址空间,简化内存管理。
  • 保护每个进程的地址空间不被其它进程破坏。

物理寻址和虚拟寻址

计算机的主存被组织成一个由M个连续的字节大小的单元组成的数组。每字节都有一个唯一的物理地址(Physical Address,PA)。第一个字节地址为0。CPU访问内存的最自然方式就是使用物理地址,这种方式称为物理寻址

现代处理器使用一种称之为虚拟寻址(virtual addressing)的寻址形式。CPU生成一个虚拟地址(VA),这个虚拟地址被发送到主存之前首先转换成合适的物理地址。叫做地址翻译(address translation)。CPU芯片上叫做内存管理单元(Memory Management Unit,MMU)的专用硬件利用存放在主存中的查询表来动态翻译虚拟地址。

地址空间

地址空间(address space)是一个非负整数地址的有序集合。如果整数是连续的,是一个线性地址空间。CPU从一个N=2**n个地址的地址空间中生成虚拟地址,称为虚拟地址空间。现代系统为32位或者64位虚拟地址空间。主存中的每字节都有一个选自虚拟地址空间的虚拟地址和一个选自物理地址空间的物理地址。

虚拟内存作为缓存

概念上,虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单员组成的数组。每个字节都有唯一的虚拟地址,对应到数组的索引。磁盘数组上的内容被缓存到主存中。磁盘上的数据被分割成块,作为磁盘和主存的传输单元。VM系统将虚拟内存分割为虚拟页(VP),虚拟页大小固定。类似的,物理内存被分割为物理页(PP),物理页也称为页帧(page frame)。

任意时刻,虚拟页面的集合都分为三个不相交的子集:

  • 未分配的:未分配的块没有任何数据,不占用任何磁盘空间。
  • 缓存的:当前已缓存在物理内存中的已分配页。
  • 未缓存的:未缓存在物理内存中的已分配页。

页表

SRAM缓存表示CPU和主存之间的L1、L2和L3高速缓存,DRAM缓存表示虚拟内存系统的缓存,它在主存中缓存虚拟页。

DRAM缓存不命中的代价是极大的,因为要由磁盘来服务。操作系统对DRAM缓存使用了很复杂精密的替换算法。

虚拟内存系统必须有某种方法来判断一个虚拟页是否缓存在DRAM中的某个地方,确定虚拟页存放在哪个物理页中。不命中,还要判断虚拟页存放在磁盘的哪个位置,在物理内存中选择一个牺牲页,并将虚拟页从磁盘复制到DRAM中,替换这个牺牲页。

这些功能由操作系统软件、MMU和一个存放在物理内存中的叫做页表(page table)的数据结构提供。页表将虚拟页映射到物理页,每次MMU将虚拟地址转换成物理地址时,都会读取页表。按操作系统负责维护页表,以及在磁盘与DRAM之间来回传送页。

页表是一个页表条目(PTE)的的数组。虚拟地址空间中的每个页在页表中一个固定偏移量处都有个PTE。每个PTE可以假设为由一个有效位(valid bit)和一个n位地址字段组成。有效位表示该虚拟页当前是否被缓存在DRAM中。

页命中与缺页

DRAM缓存不命中称之为缺页(page fault)。缺页异常调用内核中的缺页异常处理程序,该程序会选择一个牺牲页,进行交换。

在磁盘和内存之间传送页的活动叫做交换(swapping)或者页面调度(paging)。当只有不命中发生时,才换入页面的策略称之为按需页面调度。现代操作系统都采用这种方式。

局部性

虚拟内存工作的非常好,这归功于局部性。尽管在整个运行过程中程序引用的页面总数可能超过物理内存的总大小,但局部性保证了在任意时刻,程序将趋向于在一个较小的活动页面(active page)集合上工作,这个集合叫工作集(working set)或者常驻集合(resident set)。初始开销将工作集调度到内存之中。如果工作集的大小超出了物理内存的大小,那么程序将产生抖动(thrashing),这时页面将不断地换进换出。

内存管理

实际上,系统为每一个进程提供一个单独的页表,因而也是一个独立的虚拟地址空间。多个虚拟页面可以映射到同一个共享物理页面上。

按需调度页面和独立的虚拟地址空间的结合,对内存管理有深远影响。

简化加载

虚拟内存使得向内存中加载可执行文件和共享文件变得更容易。Linux加载器为代码和数据分配虚拟页,标记为无效的(未被缓存的),页表条目指向目标文件的适当位置。加载器不实际从磁盘向内存实际复制数据。只有当被使用时,才会按需自动调入数据页。

将一组连续的虚拟页映射到任意一个文件中的任意位置的表示法称作内存映射(memory mapping)。Linux提供了mmap的系统调用,允许应用程序自己做内存映射。

简化内存分配

当用户进程要求额外的堆空间是时(malloc),操作系统分配适当个连续的k个虚拟内存页面,并把他们映射到物理内存中任意位置的k个任意的物理页面。

内存保护

PTE上还有些额外位,SUP位表示进程是否运行在内核模式下才能访问本页。READ位和WRITE位控制对页面的读和写。违反了这些许可,触发一个一般保护故障,报告为段错误(segmentation fault)。