2017-2018-1 20155324 《信息安全系统设计基础》第十一周学习总结 2017-2018-1 20155324 《信息安全系统设计基础》第十一周学习总结

教材学习内容总结

虚拟存储器

  • 三个能力
  1. 它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,高效的使用了主存
  2. 它为每个进程提供了一致的地址空间,从而简化了存储器管理
  3. 它保护了每个进程的地址空间不被其他进程破坏
  • 作为缓存的工具

地址翻译

1、页面

  • 虚拟页VP(虚拟存储器),每个虚拟页大小为P=2^平字节。
  • 物理页PP(物理存储器),也叫页帧,大小也为P字节。

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

未分配的:VM系统还没分配、创建的页,不占用任何磁盘空间。
缓存的:当前缓存在物理存储器中的已分配页。
未缓存的:没有缓存在物理存储器中的已分配页。

2、页表

一个数据结构,存放在物理存储器中,将虚拟页映射到物理页。

(1)页表就是一个页表条目PTE的数组。

PTE:由一个有效位和一个n位地址字段组成的,表明了该虚拟页是否被缓存在DRAM中。

PTE的三个许可位:

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

3、缺页

指DRAM缓存不命中。

缺页异常:会调用内核中的缺页异常处理程序,选择一个牺牲页。

页面调度(交换):磁盘和存储器之间传送页的活动。

按需页面调度:直到发生不命中时才换入页面的策略,所有现代系统都使用这个。

4、虚拟存储器中的局部性

局部性原则:保证了在任意时刻,程序将往往在一个较小的活动页面集合上工作,这个集合叫做工作集/常驻集。

颠簸:工作集大小超出了物理存储器的大小。

只要程序有良好的时间局部性,虚拟存储器系统就能工作的相当好。

  • 作为存储器管理的工具

操作系统为每个进程提供了一个独立的页表,也就是一个独立的虚拟地址空间。

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

多个虚拟页面可以映射到同一个共享物理页面上。

按需页面调度和独立的虚拟地址空间的结合简化了链接和加载、代码和数据共享,以及应用程序的存储器分配。

  • 作为存储器保护的工具

通过在PTE上添加一些额外的许可来控制对一个虚拟页面的内容访问。

  • 地址翻译

2017-2018-1 20155324 《信息安全系统设计基础》第十一周学习总结
2017-2018-1 20155324 《信息安全系统设计基础》第十一周学习总结

用页表实现映射

2017-2018-1 20155324 《信息安全系统设计基础》第十一周学习总结
2017-2018-1 20155324 《信息安全系统设计基础》第十一周学习总结

  • 页面命中时,CPU硬件执行步骤:
处理器生成虚拟地址,传给MMU
MMU生成PTE地址,并从高速缓存/主存请求得到他
高速缓存/主存向MMU返回PTE
MMU构造物理地址,并把它传给高速缓存/主存
高速缓存/主存返回所请求的数据给处理器。
  • 处理缺页时,CPU硬件执行步骤
处理器生成虚拟地址,传给MMU
MMU生成PTE地址,并从高速缓存/主存请求得到他
高速缓存/主存向MMU返回PTE
PTE中有效位为0,触发缺页异常
确定牺牲页
调入新页面,更新PTE
返回原来的进程,再次执行导致缺页的指令,会命中
多级页表

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

地址翻译:

2017-2018-1 20155324 《信息安全系统设计基础》第十一周学习总结
2017-2018-1 20155324 《信息安全系统设计基础》第十一周学习总结

存储器

  • 存储器映射

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

映射对象:

Unix文件系统中的普通文件
匿名文件(全都是二进制0)

1、共享对象

对于所有把它映射到自己的虚拟存储器进程来说都是可见的。即使映射到多个共享区域,物理存储器中也只需要存放共享对象的一个拷贝。

2、私有对象

运用写时拷贝的技术,在物理存储器中只保存有私有对象的一份拷贝。

3、fork函数:应用了写时拷贝技术。为每个进程保持了私有地址空间的抽象概念。

4、execve函数:将程序加载到存储器。

Execve("a.out",NULL,NULL);

步骤:

删除已存在的用户区域。 
映射私有区域。 
映射共享区域。 
设置程序计数器。

5、map函数:

(1)创建新的虚拟存储器区域。

#include <unistd.h>
#include <sys/mman.h>

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
//成功返回指向映射区域的指针,若出错则为-1

(2)删除虚拟存储器

#include <sys/mman.h>、

int munmap(void *start, size_t length);
//成功返回0,失败返回-1

从start开始删除,由接下来length字节组成的区域。

动态存储分配

动态存储分配,即指在目标程序或操作系统运行阶段动态地为源程序中的量分配存储空间,动态存储分配包括栈式或堆两种分配方式。需要主要的是,采用动态存储分配进行处理的量,并非所有的工作全部放在运行时刻做,编译程序在编译阶段要为其设计好运行阶段存储组织形式,并为每一个数据项安排好它在数据区中的相对位置。

直接存储分配方式

直接存储分配方式要求存储器的可用空间已经确定,且确保各程序所用的地址之间互不重叠。缺点是用户感到不方便,存储器的利用率也不高。

静态存储分配方式

静态存储分配方式中。在程序被装入、连接时,才确定它们在主存中的相应位置(物理地址)。系统必须分配其要求的全部存储空间.否则不能装入该用户程序。程序将占据着分配给它的存储空间直到程序结束。该存储空间的位置固定不变,也不能动态地申请存储空间。这种方式无法实现用户对存储空间的动态扩展,而且也不能有效地实现存储器资源的共享。

动态存储分配方式

动态存储分配方式是不一次性将整个程序装入到主存中。可根据执行的需要,部分地动态装入。同时,在装入主存的程序不执行时,系统可以收回该程序所占据的主存空间。再者,用户程序装入主存后的位置,在运行期间可根据系统需要而发生改变。此外,用户程序在运行期间也可动态地申请存储空间以满足程序需求。由此可见,动态存储分配方式在存储空间的分配和释放上,表现得十分灵活,现代的操作系统常采用这种存储方式。

垃圾收集算法

回收机制:以“GC Roots”为根,做可达性分析。可作为GC Roots的对象包括:1)虚拟机栈中引用的对象;2)类静态属性引用的对象;3)方法区中常量引用的对象;4)本地方法栈中JNI(即native方法)引用的对象。

  • 垃圾收集器概述

关于垃圾收集器语境中的并行与并发: (区分操作系统中提到的并行与并发) 并行(Parellel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。

并发(Concurrent):指用户线程与垃圾收集器线程同时执行(但不一定是并行的,可能会交替执行),用户线程在继续运行,而垃圾收集器运行于另一个CPU上。

  • 垃圾收集器种类

回收young generation和tenured generation的垃圾收集器不同,且选定一者的collector后也会限制另一者的选择。

C语言中与存储器有关的错误

  • 间接引用坏指针
  • 读未初始化的存储器
  • 允许栈缓冲区溢出
  • 错误地假设指针和它们指向的对象是相同大小的
  • 造成错位错误
  • 引用指针,而不是它所指向的对象
  • 误解指针运算
  • 引用不存在的变量
  • 引用空闲堆块中的数据
  • 引起存储器泄漏

间接引用坏指针

scanf("%d",&val);//正确,应当传递给scanf变量地址

scanf("%d",val);//错误,scanf会将val值解释为地址,假设不幸的是val的值确实对应于虚存的合法读写区域,就覆盖了存储器

允许栈缓冲区溢出

void bufoverflow()  
{  
    char buf[64];  

    gets(buf); /* 不检查输入串的大小就写入栈中的目标缓冲区会导致缓冲区溢出。应使用限制输入串大小的fgets函数 */  
    return;  
}

造成错位错误

int **makeArray2(int n, int m)  
{  
    int i;  
    int **A = (int **) malloc(n *sizeof(int *));  

    for (i = 0; i <= n; i++)  /*低级的越界错误,i < n 而不是i <= n */
        A[i] = (int *) malloc(m * sizeof(int));  

    return A;  
} 

误解指针运算

int *search(int *p, int val)  
{  
    while (*p && *p != val)  
        p += sizeof(int); /* 指针是以指向的对象大小为单位来进行算术操作的。遍历数组应是p++。*/  

    return p;  
}  

引起存储器泄漏

void leak(int n)  
{  
    int *x = (int *)malloc(n *sizeof(int));  

    return; /* 未释放就返回导致x成为堆中的垃圾 */  
}  

其他(感悟、思考等,可选)

本学期课本上的内容已经接近尾声了,通过课本学到了不少的知识,但是想要完全掌握需要在以后的学习与生活中更加努力的去运用。

代码托管

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 85/85 1/1 5/5
第二周 150/230 1/2 10/15
第三周 50/280 1/3 7/22
第四周 70/350 1/4 5/27
第五周 100/450 2/6 5/32
第六周 50/500 1/7 10/42
第七周 70/570 2/9 10/55
第八周 80/650 1/10 8/63
第九周 100/750 3/13 8/71
第十周 80/830 1/14 8/79
第十一周 50/880 2/16 10/89

尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。

参考:软件工程软件的估计为什么这么难软件工程 估计方法

  • 计划学习时间:XX小时

  • 实际学习时间:XX小时

  • 改进情况:

(有空多看看现代软件工程 课件
软件工程师能力自我评价表
)

参考资料