教材学习内容总结
虚拟存储器
虚拟存储器的三个重要能力:
1、它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,高效的使用了主存。
2、它为每个进程提供了一致的地址空间,从而简化了存储器管理。
3、它保护了每个进程的地址空间不被其他进程破坏。
程序员需要理解虚拟存储器的三个原因:
1、虚拟存储器是中心的:它是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的交互中心;
2、虚拟存储器是强大的:它可以创建和销毁存储器片、可以映射存储器片映射到磁盘某个部分等等;
3、虚拟存储器若操作不当则十分危险。
物理和虚拟寻址
计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组,每字节都有一个唯一的物理地址(PA)。CPU根据物理地址访问存储器的方式是物理寻址。
使用虚拟寻址时,CPU通过生成一个虚拟地址VA来访问主存,这个虚拟地址在被送到存储器之前先转换成适当的物理地址,地址翻译通过CPU芯片上的存储器管理单元完成。
虚拟存储器的基本思想
主存中的每个字节都有一个选自虚拟地址空间的虚拟地址和一个选自物理地址空间的物理地址。
虚拟存储器作为缓存的工具
虚拟存储器——虚拟页(VP),每个虚拟页大小为P=2^p字节。
任意时刻,虚拟页面的集合都被分为三个不相交的子集:
未分配的:VM系统还没分配(创建)的页,不占用任何磁盘空间。
缓存的:当前缓存在物理存储器中的已分配页。
未缓存的:没有缓存在物理存储器中的已分配页。
DRAM缓存的组织结构
不命中处罚很大
是全相联的——任何虚拟页都可以放在任何的物理页中
替换算法精密
总是使用写回而不是直写
页表
页表:是一个数据结构,存放在物理存储器中,将虚拟页映射到物理页,就是一个页表条目的数组。
页表就是一个页表条目PTE的数组。
PTE:由一个有效位和一个n位地址字段组成的,表明了该虚拟页是否被缓存在DRAM中。
页表的组成:有效位+n位地址字段
如果设置了有效位:地址字段表示DRAM中相应的物理页的起始位置,这个物理页中缓存了该虚拟页。
如果没有设置有效位:
空地址:表示该虚拟页未被分配
不是空地址:这个地址指向该虚拟页在磁盘上的起始位置。
页命中
当CPU读取一个字的时候,地址翻译硬件将虚拟地址作为一个索引来定位PTE,并从存储器中读取它。
缺页
缺页:就是指DRAM缓存不命中。
缺页异常:会调用内核中的缺页异常处理程序,选择一个牺牲页。
页:虚拟存储器的习惯说法,就是块
交换=页面调度:磁盘和存储器之间传送页的活动
按需页面调度:直到发生不命中时才换入页面的策略,所有现代系统都使用这个。
局部性原则保证了在任意时刻,程序将往往在一个较小的活动页面集合上工作,这个集合叫做工作集/常驻集。
所以只要程序有良好的时间局部性,虚拟存储器系统就能工作的相当好。
颠簸:工作集大小超出了物理存储器的大小。
虚拟存储器作为存储器管理的工具
操作系统为每个进程提供了一个独立的页表,也就是一个独立的虚拟地址空间。
多个虚拟页面可以映射到同一个共享物理页面上。
存储器映射
存储器映射是将一组连续的虚拟页映射到任意一个文件中的任意位置的表示法。
按需页面调度和独立的虚拟地址空间的结合简化了链接和加载、代码和数据共享,以及应用程序的存储器分配。
简化链接:独立的地址空间允许每个进程的存储器映像使用相同的基本格式,而不管代码和数据实际存放在物理存储器的何处。
简化加载:虚拟存储器使得容易想存储器中加载可执行文件和共享文件对象。
简化共享:独立地址空间为操作系统提供了一个管理用户进程和操作系统自身之间共享的一致机制。
简化存储器分配:虚拟存储器为向用户进程提供一个简单的分配额外存储器的机制。
- 虚拟存储器作为存储器保护的工具通过在PTE上添加一些额外的许可来控制对一个虚拟页面的内容访问。
- PTE的三个许可位:
SUP:表示进程是否必须运行在内核模式下才能访问该页
READ:读权限
WRITE:写权限
地址翻译
地址翻译:一个N元素的虚拟地址空间(VAS)中的元素和一个M元素的物理地址空间(PAS)之间的映射。
MAP: VAS → PAS ∪ ∅
MAP = A' ,如果虚拟地址A处的数据在PAS的物理地址A'处
MAP = ∅ ,如果虚拟地址A处的数据不在物理存储器中
1、CPU中的一个控制寄存器页表基址寄存器指向当前页表,n位的虚拟地址包含两个部分:一个p位的虚拟页面偏移(VPO) 和一个(n-p)位的虚拟页号,页表条目中的物理页页号和虚拟地址中的VPO串联起来,就得到了相应的物理地址。
2、当页面命中时,CPU硬件执行步骤
处理器生成虚拟地址,传给MMU
MMU生成PTE地址,并从高速缓存/主存请求得到他
高速缓存/主存向MMU返回PTE
MMU构造物理地址,并把它传给高速缓存/主存
高速缓存/主存返回所请求的数据给处理器。
3、处理缺页时,CPU硬件执行步骤
处理器生成虚拟地址,传给MMU
MMU生成PTE地址,并从高速缓存/主存请求得到他
高速缓存/主存向MMU返回PTE
PTE中有效位为0,触发缺页异常
确定牺牲页
调入新页面,更新PTE
返回原来的进程,再次执行导致缺页的指令,会命中
动态存储器分配
- 当运行时需要额外虚拟存储器时,使用动态存储器分配器维护一个进程的虚拟存储器区域。
分配器的两种风格:
1、显示分配器:要求应用显式地释放任何已经分配的块。
2、隐式分配器:要求分配器检测一个已分配块何时不再被程序所使用,就释放这个块。也叫做垃圾收集器。
malloc和free函数
系统调用malloc函数,从堆中分配块:
#include <stdlib.h>
void *malloc(size_t size);
成功返回指针,指向大小至少为size字节的存储器块,失败返回NULL
系统调用free函数来释放已分配的堆块:
#include <stdlib.h>
void free(void *ptr);
无返回值
ptr参数必须指向一个从malloc、calloc或者reallov获得的已分配块的起始位置。
- 使用动态存储器分配原因:经常直到程序实际运行时,才知道某些数据结构的大小。
分配器的要求和目标
显示分配器的要求:
处理任意请求序列
立即响应请求
只使用堆
对齐块
不修改已分配的块
目标:
最大化吞吐率:最大化存储器利用率——峰值利用率最大化
吞吐率:每个单位时间里完成的请求数
垃圾收集
- 垃圾收集器是一种动态存储分配器,自动释放程序已经不再需要的已分配块(垃圾)。
基本知识
垃圾收集器将存储器视为一张有向可达图,图的节点被分配为一组根节点和一组堆节点。当存在一条从任意根节点出发到并到达P的有向路径时,就称节点P是可达的。
- Mark&Sweep垃圾收集器
Mark&Sweep垃圾收集器由标记阶段和清除阶段组成,标记阶段标记出根节点所有可达的和已分配的后继,清除阶段释放每个未被标记的已分配块。
在对Mark&Sweep的描述中使用下列函数:
ptr isPtr(ptr p):如果p指向一个已分配块中的某个字,那么就返回一个指向这个块起始位置的指针b,否则返回NULL。
int blockMarked(ptr b):如果已经标记了块b,就返回true。
int blockAllocated(ptr b):如果块b是已分配的,就返回true。
void markBlock(ptr b):标记块b。
int length(ptr b):返回块b的以字为单位的长度(不包括头部)。
void unmarkBlock(ptr b):将块b的状态由已标记的改为未标记的。
ptr nextBlock(ptr b):返回堆中块b的后继。
C程序中常见的与存储器有关的错误
1、间接引用坏指针
在进程的虚拟地址空间中有较大的洞,没有映射到任何有意义的数据,如果试图引用一个指向这些洞的指针,操作系统就会以段异常来终止程序。典型的错误是:scanf("%d",val);,没有加&符号
2、读未初始化的存储器
3、允许栈缓冲区溢出
如果一个程序不检查输入串的大小就写入栈中的目标缓冲区,程序就会出现缓冲区溢出错误。
4、引用指针,而不是他所指向的对象。
注意C的优先级和结合性
结对对象20155209林虹宇
代码托管
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 7/7 | 1/1 | 4/4 | |
第三周 | 62/69 | 2/3 | 15/19 | |
第五周 | 161/230 | 2/5 | 22/41 | |
第七周 | 82/312 | 1/6 | 17/58 | |
第八周 | 140/452 | 1/7 | 15/73 | |
第九周 | 57/509 | 3/10 | 18/91 | |
第十一周 | 104/613 | 1/11 | 14/105 |