虚拟内存
易混概念:
- 虚拟页VP标识的是硬盘,物理页是内存的子集,当我们取数据是如果虚拟地址标识的数据在页表中可以找到且有效位为1,则表示可以直接在物理内存中取值;
- 全相联:任意一个节点可以连接到对面的任意一个节点,而且可以多对多;
- 写程序时要注意程序的时间局部性和空间局部性,程序无缘无故很慢则可以利用
getrusage
判断是否发生了抖动;
一.引言
本文是对《深入理解计算机系统》一书第九章部分内容的汇总,旨在对虚拟内存有个基本了解,进而加深对多线程、并发、加锁、竞态条件等相关——可能也是无关的知识的理解。
学透此部分应该掌握两点:
- 虚拟内存是如何工作的;
- 应用程序如何使用和管理虚拟内存;
1.1 基本介绍
为了更加有效的管理内存,现代操作系统提供了一种对主存的抽象叫虚拟内存VM。虚拟内存是硬件异常、内和软件、硬件地址翻译、主存、磁盘的完美交互。
虚拟内存提供了三个重要的能力:
- VM将主存看成存储在硬盘上的++地址空间的高速缓存++,在主存中只保留活动区域,并且根据需要在主存和硬盘之间以块为单位传送数据,通过这种方式,VM搞笑的使用了主存;
- 为每个进程提供了一致的地址空间(相对独立的地址空间),从而简化了内存管理;
- 保护了每个进程的地址空间不被其他进程破坏——相对独立;
1.2 VM如何工作
如上,虚拟地址如何工作涉及虚拟地址寻址VA、地址空间、虚拟地址作为缓存工具,页表条目PTE(page table entry)职责、页命中、缺页、malloc分配页面、局部性在VM中的作用,VM作为内存管理工具、VM作为内存保护工具、地址翻译和垃圾回收等部分。
还有一些内容此博文未讲到,如内存映射、动态内存分配、案例研究Intel Core i7/Linux、c语言中与内存有关的错误,待以后更新。
二.虚拟地址寻址和地址空间
2.1 虚拟寻址和内存保护
将主存看成有M个连续的一个字节大小的单元组成的数组(2^32 byte=4G,因此32位的地址空间最大支持4G内存)。
物理寻址就是CPU字节使用物理地址。示意图如下:
虚拟寻址相对于物理寻址Physical Address PA来说的。CUP使用虚拟地址简介访问主存,CUP上的内存管理单元MMU利用主存中的页表将虚拟地址翻译成物理地址,从而完成访问。示意图如下:
每个线程都有自己的页表,他们虚拟地址映射到的物理地址可能有交集,通过页表的许可位可以控制某个线程是否可以修改、读取这些数据,从而保证共享数据的安全性。示意图如下(VM作为内存保护工具):
- sup(super)指用户是否必须运行在内核模式下才能访问该页;
- 虚拟地址是连续的,对应的页表也是连续的,不管是否分配。
指令违反这些许可条件会出发CUP的保护机制。
2.2 地址空间
计算机中用整数位表示虚拟地址空间,因此地址空间往往是2的幂。现代操作系统支持32位或者64位,而32位地址空间最大支持2^32Byte=4G的寻址。
?物理地址可以理解为之前提到的M个连续数组的下标?
主存中的每个直接都至少有一个选自虚拟地址空间的虚拟地址。
三.VM作为缓存工具
3.1 VM作为缓存管理工具
- 虚拟内存是放在磁盘上的N个连续的字节组成的数组。 虚拟内存被分割为大小固定的块,叫虚拟页;
- 页表page_table_entry常驻内存中;
- 物理内存被分割为与虚拟页大小相同的块,叫物理页或者页帧page frame;
虚拟页面由三个不想交的集合组成:缓存的、未缓存的和未分配的:
- **缓存的:已经分配并且缓存在物理内存中的虚拟页;
- 为缓存的:页表中有次虚拟页的地址,但是有效位为0,即数据未放进物理内存;
- 为分配的:VM系统还未创建、分配的页。
3.2 DRAM缓存组织结构
DRAM比SRAM慢10倍,硬盘比DRAM慢100 000倍,DRAM的不命中比SRAM的不命中开销要高很多。因此虚拟页往往很大,通常是4KB~2MB.
3.3 页表 page table,页表条目PTE,地址翻译
地址翻译硬件通过读取常驻内初的页表将虚拟地址翻译为物理地址,操作系统维护页表内容,并且在磁盘和内存之间传送页。
页表是页表条目PTE page table entry的集合,PTE由有效位和地址字段两部分组成:有效位有效则地址字段表示数据在DRAM中相应的物理页的起始位置;有效位无效且地址字段为空则表示这个PTE还未分配虚拟页;有效位无效但地址字段不为空,则地址位表示虚拟地址在硬盘上的起始位置。三种状态的示意图如下:
DRAM缓存是全相联的,即任意物理页可以包含任意虚拟页。
3.4 页命中
如果CUP读取的虚拟地址已经在页表条目PTE中缓存,即存放在物理内存中,则称为页命中,缓存命中。
3.5 缺页page fault
- 如果CUP读取的虚拟地址为缓存在页表中,则称为缺页。
- 缺页会触发缺页异常,缺页异常调用内核中的却也异常处理程序。
- 程序选择在物理内存中选择一个牺牲页,将CUP读取的虚拟地址放在这个牺牲页中。如果牺牲页被修改过,则它还需要写回硬盘。
- 内核程序更新PTE3;
- 内核程序重启缺页导致的指令;
- 指令重新把虚拟地址发送到地址翻译硬件。
相关概念:
- 页面调度/交换swapping:磁盘和内存之间传送页的活动;
- 页从磁盘换入内存,从内存换出硬盘;
- 按需页面调度 demand paging:当有不命中发生时,才换入页面的策略。
3.5 局部性和抖动
虽然程序引用的页面总数可能超过物理内存中的大小,导致缺页。但是程序总是倾向于在较小的活动页面active page,即常驻集合resident set或称工作集work set。因此在工作集调度到内存,之后的页面命中将不会产生太多的磁盘流量。这就是局部性locality。我们平时写程序时要特别注意程序的空间局部性和时间局部性。
如果工作集,即常驻集合大小超过了物理内存大小,则页面将不断换入换出,这种状态叫做抖动thrashing。
程序非常慢时可以利用Linux的getrasage
函数查看缺页的数量,判断是否产生了抖动。
四.VM作为内存管理工具
操作系统负责维护页表,它为每个进程提供了一个独立的页表,即一个独立的虚拟地址空间。如图所示:
多个虚拟页面可以映射到同一个物理页面上。
按需页面调度和独立的地址空间对内存管理产生了深远的影响:
- 进程地址空间如下图所示:每个进程都有一致的基本格式,而不用管代码和数据的具体物理位置。例如64位地址空间代码总是从虚拟地址的0X400000开始,数据段紧跟代码后边。这种一致性简化了连接器的设计和实现。 有些类似于jvm屏蔽了各种硬件和操作系统对内存访问的差异,让java程序在各种平台达到已知的内存访问的差异。
- 简化加载、共享、内存分配。
待以后了解相关知识后展开讲。
五.虚拟内存作为内存的保护工具
通过页表的许可位。在页表小节有讲解。
六.地址翻译
6.1 使用页表进行翻译的基本思路
翻译的结果可能定位到物理地址,可能是空集—当虚拟页为缓存的时候。
- CUP中的页表基址寄存器page table base register指向当前页表(当前线程使用的页表),PTBR每次只能指向一个页表,因此线程切换时CUP寄存器也需要指向不同的页表,如果页表太大则换入的页表会覆盖挂起线程的页表,这就是所谓的线程切换的开销;
- 虚拟页的地址包好两个部分:虚拟页号定位到一个PTE,即在页表中的位置,CUP的MMU计算;
- MMU将页表中的物理页号和也你也偏移量串联起来得到相应的物理地址——所以物理地址不是仅由页表计算得到的;
- 物理地址也是有两部分组成:物理页号和物理页偏移量。PPO和VPO位数相同。
页命中示意图
CUP执行步骤是:
- CUP生成物理地址,交给MMU的地址翻译硬件;
- MMU通过虚拟地址的虚拟页号定位到PTE,想高速缓存或者主存请求获取此PTE数据;
- cache/主存向MMU返回PTE;
- MMU利用VPO和PPN构造物理地址,在传回高速缓存/主存;
- cache/主存返回请求的数据,直接给处理器。
缺页示意图
与页命中的不同之处是:
- PTE有效位是0,则MMU触发却也异常,并传递给系统内核相应的处理程序;
- 处理程序选择牺牲页,如修改则换出磁盘,更新物理内存中的牺牲页;
- 程序更新内存中的PTE:有效位和地址段都要跟新;
- 缺页处理程序返回,并重启导致缺页的指令。
6.2 使用物理地址访问高速缓存SRAM
多个进程同时在高速缓存和存储块中共享来自虚拟地址页面的块很简单;
VM中页表的许可位标识进程对某块地址有何访问权限。使用物理地址访问SRAM时,多个进程访问权限的检查由MMU的地址翻译硬件完成。
6.3 利用翻译后备缓冲器TLB translation lookaside buffer 加速地址翻译
TLB是MMU中的一个缓存硬件,原理同PTE,但是分为三段:
- “从虚拟页号中提取出来用于组选择和行选择的TLB索引和TLB标记”;
- 如图如果TLB有2^t个组,则标记由VPN剩余部分组成。
使用TLB进行寻址的过程如下:
- CUP产生一个虚拟地址;
- 2/3对应MMU从TLB中取出相对应的PTE。
- MMU将虚拟地址翻译成物理地址,并向cache/内存请求数据;
**不命中的时候MMU会从缓存/内存中取出对应的PTE,然后放在TLB中。
TLB的优点是:所有的地址翻译步骤都在芯片上的MMU中执行,速度快。
6.4 其他
此外还有多级页表的地址翻译和端到端的地址翻译。