20145218 《信息安全系统设计基础》第十四周学习总结
教材学习内容总结
- 虚拟存储器是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每个进程提供了一个大的、一致的和私有的地址空间。
- 虚拟存储器的三个重要功能:
- 将主存看做是一个存储在磁盘上的地址空间的高速缓存,在主存中只保护活动区域。
- 为每个进程提供了一致的地址空间,从而简化了存储器管理。
- 保护了每个进程的地址空间不被其他进程破坏。
9.1 物理和虚拟寻址
- 物理寻址:主存被组织成一个由M个连续的字节大小的单元组成的数组,依次类推的寻址方式称为物理寻址。
- 虚拟寻址:CPU生成一个虚拟地址(VA)来访问主存,在被传送到存储器之前先转换成适当的物理地址。地址翻译通过CPU芯片上的存储器管理单元完成。
- 地址翻译:把一个虚拟地址转换为物理地址的任务。需要CPU硬件和操作系统之间的紧密合作。
9.2 地址空间
- 地址空间是一个非负整数地址的有序集合:
{0,1,2,......}
- 线性地址空间:地址空间中的整数是连续的。
- 虚拟地址空间:CPU从一个有N=2^n个地址的地址空间中生成虚拟地址。
- 物理地址空间:与系统中的物理存储器的M个字节相对应。
- 地址空间大小:由表示最大地址所需要的位数来描述。
虚拟存储器作为缓存的工具
- 物理存储器被分割为物理页(PP)。
- VM系统将虚拟存储器分割为虚拟页(VP),大小为P=2^p字节,虚拟页面的集合分为三个不相交的子集:
- 未分配的:系统还未分配的页,未存储数据,不占用磁盘空间。
- 缓存的:当前缓存在物理存储器中的已分配页
- 未缓存的:没有缓存在物理存储器中的已分配页。
DRAM缓存的组织结构
- DEAM缓存的组织结构完全是由巨大的不命中开销驱动。
- DRAM缓存是全相联的,任何虚拟页都可以放置在任何的物理页中。
- DRAM缓存总是使用写回。
页表
- 页表:将虚拟页映射到物理页,就是一个页表条目的数组。
- PTE:由一个有效位和一个n位地址字段组成的,表明了该虚拟页是否被缓存在DRAM中。
页命中
- 当CPU读取一个字的时候,地址翻译硬件将虚拟地址作为一个索引来定位PTE,并从存储器中读取它。
缺页
- DRA缓存不命中称为缺页。
- 在不命中发生时,换入页面的策略称为按需页面调度。
9.4 虚拟存储器作为存储器管理的工具
- 按需页面调度和独立的虚拟地址空间的结合简化了链接和加载、代码和数据共享,以及应用程序的存储器分配。
- 简化链接:独立的地址空间允许每个进程的存储器映像使用相同的基本格式,而不管代码和数据实际存放在物理存储器的何处。
- 简化加载:虚拟存储器使得容易想存储器中加载可执行文件和共享文件对象。
- 简化共享:独立地址空间为操作系统提供了一个管理用户进程和操作系统自身之间共享的一致机制。
- 简化存储器分配:虚拟存储器为向用户进程提供一个简单的分配额外存储器的机制。
9.5 虚拟存储器作为存储器保护的工具
- 通过在PTE上添加一些额外的许可来控制对一个虚拟页面的内容访问。
9.6 地址翻译
-
地址翻译是一个N元素的虚拟地址空间(VAS)中的元素和一个M元素的物理地址空间(PAS)之间的映射。
MAP:VAS→PAS∪空
-
MAP(A)=
-
A':如果虚拟地址A处的数据在PAS的物理地址A处'
-
空:如果虚拟地址A处的数据不在物理存储器中
-
地址翻译过程
-
CPU中的一个控制寄存器,页表基址寄存器指向当前页表;
-
n位的虚拟地址包括以下两个部分:一个p位的虚拟页面偏移和一个(n-p)位的虚拟页号;
-
MMU用后者选择适当的PTE,再将物理页号和虚拟地址中的VPO串联起来得到物理地址;
-
因为物理和虚拟页面都是P字节的,所以物理页面偏移和VPO是相同的。
利用TLB加速地址翻译 -
在MMU中包括了一个关于PTE的小的缓存,称为翻译后备缓冲器(TLB),其中每一行都保存着一个由单个PTE组成的块。
-
CPU产生一个虚拟地址。
-
MMU从TLB中取出相对应的PTE。
-
MMU将这个虚拟地址翻译成一个物理地址,并将它发送到高速缓存/主存。
-
高速缓存/主存将所请求的数据字返回给CPU。
多级页表
- 用来压缩页表的常用方法是使用层次结构的页表。
9.8 存储器映射
- Linux通过将一个虚拟存储器区域与一个磁盘上的对象关联起来,以初始化这个虚拟存储器区域的内容,这个过程成为存储器映射。具体可以映射的对象有两种:
- Unix文件系统中的普通文件。一个区域可以映射到一个普通磁盘文件的连续部分。
- 匿名文件。匿名文件由内核创建,包含的全是二进制的0。
- 一旦一个虚拟页面被初始化了,它就在一个由内核维护的专门的交换文件之间换来换去。交换文件也叫交换空间,或交换区域。
共享对象
- 一个对象被映射到虚拟存储器的一个区域,要么作为共享对象,要么作为私有对象。
- 一个映射到共享对象的虚拟存储器区域叫做共享区域,类似的,也有虚拟区域。
- 私有对象时使用一种叫做写时拷贝的技术被映射到虚拟存储器中的,相应私有区域的页表条目都被标记为只读,并且区域结构被标记为私有的写时拷贝。
execve函数
- 使用execve函数将a.out程序加载到存储器的过程
Execve("a.out",NULL,NULL);
- 具体经过的步骤如下:
- 删除已存在的用户区域。
- 映射私有区域。
- 映射共享区域。
- 设置程序计数器。
使用map函数的用户级存储器映射
- Unix进程可以使用mmap函数来创建新的虚拟存储器区域,并将对象映射到这些区域当中
void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offest);
若成功则为指向映射区域的指针,若出错则为MAP_FAILDE(-1)
- munmap函数删除虚拟存储器的区域。
int munmap(void *start,size_t length);
若成功则返回0,若失败则返回-1.
9.9 动态存储器分配
动态存储器分配器
- 当运行时需要额外虚拟存储器时,使用动态存储器分配器维护一个进程的虚拟存储器区域。分配器有两种风格。
- 显示分配器:要求应用显式地释放任何已经分配的块。
- 隐式分配器:要求分配器检测一个已分配块何时不再被程序所使用,就释放这个块。也叫做垃圾收集器。
malloc和free函数
- C标准库提供了一个称为malloc程序包的显式分配器,程序通过调用malloc函数来从标准堆中分配块。
void *malloc(size_t size);
若成功则为指针,若出错则为NULL。
- 通过调用free函数来释放已分配的块。
void free(void *ptr);
分配器的目标和要求
- 显式分配器工作的约束条件:
- 处理任意请求序列。
- 立即响应请求。
- 只使用堆。
- 对齐块(对齐要求)。
- 不修改已分配的额块。
- 理想分配器的目标:
- 最大化吞吐率:吞吐率定义为每个单位时间里完成的请求数。
- 最大化存储器利用率:最有用的标准是峰值利用率。
9.10 垃圾收集
- 垃圾收集器是一种动态存储分配器。,自动释放程序已经不再需要的已分配快(垃圾)。
垃圾收集器的基本知识
- 垃圾收集器将存储器视为一张有向可达图,图的节点被分配为一组根节点和一组堆节点。当存在一条从任意根节点出发到并到达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的后继。
9.11 C语言中常见的与存储器有关的错误
- 间接引用坏指针:在进程的虚拟地址空间中有较大的洞,没有映射到任何有意义的数据,如果试图引用一个指向这些洞的指针,操作系统就会以段异常来终止程序。典型的错误是:
scanf("%d",val);
- 读未初始化的存储器:虽然bass存储器位置总是被加载器初始化为0,但对于堆存储器却并不是这样的。
- 允许栈缓冲区溢出:如果一个程序不检查输入串的大小就。写入栈中的目标缓冲区,程序就会出现缓冲区溢出错误。
- 假设指针和指向他们的对象大小是相同的。
- 造成错位错误。
- 引用指针,而不是他所指向的对象。
- 误解指针运算:忘记了指针的算术操作是以它们指向的对象的大小为单位来进行,而这种大小单位不一定是字节。
- 引用不存在的变量。
- 引用空闲堆块中的数据。
- 引起存储器泄露:当不小心忘记释放已分配块,而在堆里创建了垃圾时,就会引起存储器泄露。
课后作业中的问题和解决过程
练习9.2
确定下列虚拟地址大小(n)和页大小(P)的组合所需要的PTE数量
n | P=2^p | #PTE |
---|---|---|
16 | 4K | 16 |
16 | 8K | 8 |
32 | 4K | 1M |
32 | 8K | 512K |
因为每个虚拟页面都是 P = 2p个字节,所以在系统中总共有2n/2^p = 2^(n-p)个可能的页面,其中每个都需要一个页表条目(PTE)。
K=2^10,M=2^20,G=2^30,T=2^40,P=2^50,E=2^60
练习题9.3
给定一个32位的虚拟地址空间和一个24位的物理地址,对于下面的页面大小P,确定VPN,VPO,PPN,PPO的位数。VPN——虚拟页号;VPO——虚拟页面偏移量;PPN——物理页号;PPO——物理页面偏移量。
P = 1KB——>VPN = 22,VPO = 10,PPN = 14,PPO = 10
P = 4KB——>VPN = 20,VPO = 12,PPN = 12,PPO = 12
其他(感悟、思考等,可选)
本章对虚拟存储器的讲解让我们把之前学习过的内容,比如进程、堆栈等知识都串联起来了,会有一种“原来如此”的感觉,觉得豁然开朗。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 100/100 | 1/2 | 20/20 | |
第二周 | 92/192 | 1/3 | 18/38 | |
第三周 | 195/387 | 1/4 | 22/60 | |
第四周 | 180/567 | 0/4 | 30/90 | |
第五周 | 120/687 | 1/5 | 20/20 | |
第六周 | 130/817 | 1/6 | 18/38 | |
第七周 | 550/1367 | 1/7 | 22/60 | |
第八周 | 0/1367 | 2/9 | 30/90 | |
第九周 | 60/1427 | 2/11 | 20/20 | |
第十周 | 514/1941 | 2/13 | 18/38 | |
第十一周 | 1856/3797 | 2/15 | 22/60 | |
第十二周 | 97/3894 | 2/15 | 22/60 | |
第十三周 | 200/4094 | 1/16 | 22/60 | |
第十四周 | 100/4194 | 1/17 | 22/60 |