您的位置:首页 > 其它

20145232韩文浩《信息安全系统设计基础》第14周学习总结

2016-12-18 19:20 330 查看

教材学习内容总结

虚拟存储器是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每个进程提供了一个大的、一致的和私有的地址空间。

虚拟存储器提供了三个重要的能力:

1.它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,它高效地使用了主存。

2.它为每个进程提供了一致的地址空间,从而简化了存储器管理。

3.它保护了每个进程的地址空间不被其他进程破坏。

为何需要理解虚拟存储器?

1.虚拟存储器是中心的。虚拟存储器遍及计算机系统的所有层面,在硬件异常、汇编器、链接器、加载器、共享对象、文件和进程的设计中扮演着重要角色。理解虚拟存储器将帮助你更好地理解系统通常是如何工作的。

2.虚拟存储器是强大的。虚拟存储器给予应用程序强大的能力,可以创建和销毁存储器片 (chunk)、将存储器片映射到磁盘文件的某个部分,以及与其他进程共享存储器。理解虚拟存储器将帮助你利用它的强大功能在你的应用程序中添加动力。

3.虚拟存储器是危险的。每次应用程序引用一个变量、间接引用一个指针,或者调用一个诸如 malloc 这样的动态分配程序时,它就会和虚拟存储器发生交互。如果虚拟存储器使用不当,应用将遇到复杂危险的与存储器有关的错误。理解虚拟存储器以及诸如 malloc 之类的管理虚拟存储器的分配程序,可以帮助你避免这些错误。

9.1 物理和虚拟寻址

使用虚拟寻址时, CPU 通过生成一个虚拟地址来访问主存,这个虚拟地址在被送到存储器之前先转换成适当的物理地址。将一个虚拟地址转换为物理地址的任务叫做地址翻译。地址翻译需要 CPU 硬件和操作系统之间的紧密合作。

9.2 地址空间

地址空间是一个非负整数地址的有序集合。

如果地址空间中的整数是连续的,那么我们说它是一个线性地址空间。

在一个带虚拟存储器的系统中, CPU从一个有N=2n次方个地址的地址空间中生成虚拟地址,这个地址空间称为虚拟地址空间。

一个地址空间的大小是由表示最大地址所需要的位数来描述的。

一个系统还有一个物理地批空间,它与系统中物理存储器的M个字节相对应。

9.3 虚拟存储器作为缓存的工具

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

1.未分配的 :VM 系统还未分配(或者创建)的页。未分配的块没有任何数据和它们相关联,因此也就不占用任何磁盘空间。

2.缓存的:当前缓存在物理存储器中的己分配页。

3.未缓存的 : 没有缓存在物理存储器中的已分配页。

9.4 虚拟存储器作为存储器管理的工具

VM 简化了链接和加载、代码和数据共享,以及应用程序的存储器分配。

简化链接。独立的地址空间允许每个进程的存储器映像使用相同的基本格式,可而不管代码和数据实际存放在物理存储器的何处。

虚拟存储器还使得容易向存储器中加载可执行文件和共享对象文件。

一组连续的虚拟页映射到任意一个文件中的任意位置的表示法称做存储器映射。

Unix提供一个称为 mmap 的系统调用,允许应用程序自己做存储器映射。

简化共享。独立地址空间为操作系统提供了一个管理用户进程和操作系统自身之间共享的一致机制。一般而言,每个进程都有自己私有的代码、数据、堆以及栈区域,是不和其他进程共享的。在这种情况下,操作系统创建页表,将相应的虚拟页映射到不同的物理页面。

简化存储器分配。虚拟存储器为向用户进程提供一个简单的分配额外存储器的机制。

9.5 虚拟存储器作为存储器保护的工具

PTE的三个许可位:

SUP:表示进程是否必须运行在内核模式下才能访问该页
READ:读权限
WRITE:写权限

9.6 地址翻译

MAP: VAS → PAS ∪ ∅

MAP = A' ,如果虚拟地址A处的数据在PAS的物理地址A'处

MAP = ∅ ,如果虚拟地址A处的数据不在物理存储器中

CPU中的一个控制寄存器页表基址寄存器指向当前页表,n位的虚拟地址包含两个部分:一个p位的虚拟页面偏移(VPO) 和一个(n-p)位的虚拟页号,页表条目中的物理页页号和虚拟地址中的VPO串联起来,就得到了相应的物理地址。

TLB:翻译后备缓冲器,是一个小的、虚拟存储的缓存,其中每一行都保存着一个由单个PTE组成的块。

多级页表——采用层次结构,用来压缩页表。

以两层页表层次结构为例,好处是:

如果一级页表中的一个PTE是空的,那么相应的二级页表就根本不会存在

只有一级页表才需要总是在主存中,虚拟存储器系统可以在需要时创建、页面调入或调出二级页表,只有最经常使用的二级页表才缓存在主存中。

9.7 案例研究

PTE的三个权限位:

R/W位:确定内容是读写还是只读
U/S位:确定是否能在用户模式访问该页
XD位:禁止执行位,64位系统中引入,可以用来禁止从某些存储器页取指令

缺页处理程序涉及到的位:

A位,引用位,实现页替换算法
D位,脏位,告诉是否必须写回牺牲页

9.8 存储器映射

存储器映射:Linux通过将一个虚拟存储器区域与一个磁盘上的对象关联起来,以初始化这个虚拟存储器区域的内容的过程。

映射对象:

1.Unix文件系统中的普通文件

2.匿名文件(全都是二进制0)

共享对象对于所有把它映射到自己的虚拟存储器进程来说都是可见的。

即使映射到多个共享区域,物理存储器中也只需要存放共享对象的一个拷贝。

私有对象运用的技术:写时拷贝 。

在物理存储器中只保存有私有对象的一份拷贝。

fork 函数

当fork函数被当前进程调用时,内核为新进程创建各种数据结构,分配给它一个唯一的 PID。为了给这个新的进程创建虚拟存储器,它创建了当前进程的mm_struct、区域结构和页表的原样拷贝。

它将两个进程中的每个页面都标记为只读,并将两个进程中的每个区域结构都标记为私有的写时拷贝。

当 fork 在新进程中返回时,新进程现在的虚拟存储器刚好和调用 fork时存在的虚拟存储器相同。

当这两个进程中的任一个后来进行写操作时,写时拷贝机制就会创建新页面,因此,也就为每个进程保持了私有地址空间的抽象概念。

execve 函数

execve 函数在当前进程中加载并运行包含在可执行目标文件 a.out 中的程序,用 a.out 程序有效地替代了当前程序。加载并运行 a.out 需要以下几个步骤:

1.删除已存在的用户区域。删除当前进程虚拟地址的用户部分中的已存在的区域结构。

2.映射私有区域。为新程序的文本、数据、 bss 和栈区域创建新的区域结构。所有这些新的区域都是私有的、写时拷贝的。文本和数据区域被映射为 a.out 文件中的文本和数据区。 bss 区域是请求二进制零的,映射到匿名文件,其大小包含在 a.out 中。栈和堆区域也是请求二进制零的,初始长度为零。

3.映射共享区域。如果 a.out 程序与共享对象(或目标)链接,比如标准 C 库 libc. so,那么这些对象都是动态链接到这个程序的,然后再映射到用户虚拟地址空间中的共享区域内。

4.设置程序计数器 (PC)。 execve 做的最后一件事情就是设置当前进程上下文中的程序计数器,使之指向文本区域的入口点。

9.9 动态存储器分配

malloc 和 free 函数

malloc 函数返回一个指针,指向大小为至少 size 字节的存储器块,这个块会为可能包含在这个块内的任何数据对象类型做对齐。

sbrk 函数通过将内核的 brk 指针增加 incr来扩展和收缩堆。

如果成功,它就返回 brk 的旧值,否则,它就返回-1,并将 errno设置为 ENOMEM。如果 incr 为零,那么 sbrk 就返回 brk 的当前值。

用一个为负的 incr 来调用 sbrk 是合法的,而且很巧妙,因为返回值 (brk 的旧值)指向距新堆顶向上 abs (incr) 字节处。

显示分配器的要求:

(1)处理任意请求序列
(2)立即响应请求
(3)只使用堆
(4)对齐块
(5)不修改已分配的块


目标:

(1)最大化吞吐率:最大化存储器利用率——峰值利用率最大化
(2)吞吐率:每个单位时间里完成的请求数


碎片:虽然有未使用的存储器,但是不能用来满足分配请求。

内部碎片:发生在一个已分配块比有效载荷大的时候,易于量化。
外部碎片:发生在当空闲存储器合计起来足够满足一个分配请求,但是没有一个单独的空间块足以处理这个请求时发生。难以量化,不可预测。


分离的空闲链表

1、简单分离存储

每个大小类的空闲链表包含大小相等的块,每个块的大小就是这个大小类中最大元素的大小。

优点:分配和释放块快

缺点:容易造成碎片

2、分离适配

分配一个块:确定请求的大小类,对适当的空闲链表做首次适配,查找一个合适的块,找到一个之后,可选的分割它,并将剩余部分插入适当的空闲链表中,如果找不到合适的块,就搜索下一个更大的大小类的空闲链表,直到找到一个合适的块,如果没有合适的块,就向操作系统请求额外的堆存储器,并从这个新的堆存储器中分配出一个块,将剩余部分放置在适当的大小类中,释放块时,执行合并,并将结果放置在相应的空闲链表里。

3、伙伴系统

伙伴系统是分离适配的一种特例,每个大小类都是2的幂。

优点:快速搜索和快速合并。

缺点:内部碎片。

9.10 垃圾收集

垃圾收集器:一种动态存储分配器,它自动释放程序不再需要的已分配块,这些块被称为垃圾,自动回收堆存储的过程叫做垃圾收集。

在 C 程序的上下文中,应用调用 malloc,但是从不调用 free。反之,垃圾收集器定期识别垃圾块,并相应地调用 free,将这些块放回到空闲链表中。

C 程序的保守 Mark&Sweep

C 不会用任何类型信息来标记存储器位置。

因此,对 isPtr 没有一种明显的方式来判断它的输入参数 p 是不是一个指针。

即使我们知道 p 是一个指针,对 isPtr 也没有明 显的方式来判断 p 是否指向一个已分配块的有效载荷中的某个位置。

9.11 C程序中常见的与存储器有关的错误

间接引用坏指针

在进程的虚拟地址空间中有较大的洞,没有映射到任何有意义的数据,如果试图引用一个指向这些洞的指针,操作系统就会以段异常来终止程序。 scanf错误

读未初始化的存储器

虽然bass存储器位置总是被加载器初始化为0,但对于堆存储器却并不是这样的。假设堆存储器被初始化为0。

允许栈缓冲区溢出

如果一个程序不检查输入串的大小就写入栈中的目标缓冲区,程序就会出现缓冲区溢出错误。

假设指针和指向他们的对象大小是相同的。

一种常见的错误是假设指向对象的指针和他们所指向的对象是大小相同的。

造成错位错误

一种很常见的覆盖错误来源

引用指针,而不是他所指向的对象

注意C的优先级和结合性

误解指针运算

忘记了指针的算术操作是以它们指向的对象的大小为单位来进行,而这种大小单位不一定是字节。

引用不存在的变量

不理解栈的规则,有时会引用不再合法的本地变量。

引用空闲堆块中的数据

不理解栈的规则,有时会引用不再合法的本地变量。

引起存储器泄露

当不小心忘记释放已分配块,而在堆里创建了垃圾时,就会引起存储器泄露。

体会总结

这一章主要了解了虚拟存储器的功能、管理与使用等。虚拟存储器是对主存的一个抽象。其实它与虚拟器有许多地方类似,但又有些概念不同,需要注意学习区分。学习它的思想很重要。

学习进度条

代码行数(新增/累积)博客量(新增/累积)学习时间(新增/累积)重要成长
目标4000行16篇400小时
第一周80/801/120/20
第二周130/2101/218/38
第三周300/5101/322/60
第五周300/8101/430/90
第六周200/10101/530/120
第七周250/12601/630/150
第八周0/12601/740/190
第九周132/13921/830/220
第十周566/19581/930/250
第十一周1016/29741/1035/285
第十二周32/30061/1130/315
第十三周952/39581/1135/350
第十四周0/39581/1120/370
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: