2017-2018-20155336 《信息安全系统设计基础》第十一周学习总结
学习目标
- 理解虚拟存储器的概念和作用
- 理解地址翻译的概念
- 理解存储器映射
- 掌握动态存储器分配的方法
- 理解垃圾收集的概念
- 了解C语言中与存储器有关的错误
教材学习内容总结
物理和虚拟寻址
计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组。每宇节都有一个唯一的物理地址 。第一个字节的地址为 0,接下来的字节地址为 1,再下一个为 2, CPU 访问存储器的最自然的方式就是使用物理地址。我们把这种方式称为物理寻址。
早期的 PC 使用物理寻址,现代处理器使用的是一种称为虚拟寻址的寻址形式。
使用虚拟寻址时, CPU 通过生成一个虚拟地址来访问主存,这个虚拟地址在被送到存储器之前先转换成适当的物理地址。将一个虚拟地址转换为物理地址的任务叫做地址翻译。地址翻译需要 CPU 硬件和操作系统之间的紧密合作。 CPU 芯片上叫做存储器管理单元的专用硬件, 利用存放在主存中的查询表来动态翻译虚拟地址。注意:该表的内容是由操作系统管理的。
地址空间
-
线性地址空间:地址空间中的整数是连续的
-
虚拟地址空间:CPU从一个有
N=2^n
个地址的地址空间中生成的虚拟地址 -
物理地址空间:与系统中的物理存储器的M个字节相对应
-
一个地址空间的大小是由表示最大地址所需要的位数来描述的。
虚拟存储器的概念和作用
-
概述:虚拟存储器被组织为一个由存放在磁盘上的 N个连续的字节大小的单元组成的数组。每字节都有一个唯一的虚拟地址,这个唯一的虚拟地址是作为到数组的索引的。磁盘上数组的内容被缓存在主存中。磁盘上的数据被分割成块,这些块作为磁盘和主存之间的传输单元。
-
作用:
-
作为缓存的工具:
DRAM
缓存的组织结构:- SRAM 缓存位于 CPU 和主存之间的 Ll、 L2 和 L3 高速缓存。
- DRAM 缓存来表示虚拟存储器系统的缓存,它在主存中缓存虚拟页。
- 在存储层次结构中, DRAM 缓存的位置对它的组织结构有很大的影响。
- DRAM 缓存中的不命中比起 SRAM 缓存中的不命中要昂贵得多,因为 DRAM 缓存不命中要由磁盘来服务,而 SRAM 缓存不命中通常是由基于 DRAM 的主存来服务的。
- DRAM 缓存的组织结构完全是由巨大的不命中开销驱动的。
-
页表、页命中、缺页:
- 页表:是一个数据结构,存放在物理存储器中,将虚拟页映射到物理页,就是一个页表条目的数组
- 页表就是一个页表条目的数组
- PTE:由一个有效位和一个n位地址字段组成的
DRAM
缓存不命中称为缺页- 在磁盘和存储器之间传送页的活动叫做交换或者页面调度
- 颠簸:工作集大小超出了物理存储器的大小
-
作为存储器管理的工具:
- 多个虚拟页面可以映射到同一个共享物理页面上
- 简化链接:独立的地址空间允许每个进程的存储器映像使用相同的基本格式,而不管代码和数据实际存放在物理存储器的何处
- 简化加载:虚拟存储器使得容易想存储器中加载可执行文件和共享对象文件
- 简化共享:独立地址空间为操作系统提供了一个管理用户进程和操作系统自身之间共享的一致机制
- 简化存储器分配:虚拟存储器为向用户进程提供一个简单的分配额外存储器的机制
-
作为存储器保护的工具:
PTE
的三个许可位:- SUP:表示进程是否必须运行在内核模式下才能访问该页
- READ:读权限
- WRITE:写权限
-
地址翻译
- 地址翻译:是一个N元素的虚拟地址空间中的元素和一个M元素的物理地址空间中元素之间的映射。
- 页表基址寄存器:
- CPU中的一个控制寄存器,叫做页表基址寄存器指向当前页表。N位的虚拟地址包含两个部分:一个p位的
VPO
(虚拟页面偏移)和一个n-p
位的VPN
。MMU
利用VPN来选择适当的PTE
。将页表条目中PPN(物理页号)和虚拟地址中的VPO串联起来,就是相应的物理地址
- CPU中的一个控制寄存器,叫做页表基址寄存器指向当前页表。N位的虚拟地址包含两个部分:一个p位的
- 页面命中完全由硬件处理的,而处理缺页要求硬件和OS内核协作完成。
- 结合高速缓存和虚拟存储器:
- 大多数系统是选择物理寻址的方式来访问高速缓存。使用物理寻址,多个进程同时在高速缓存中有存储块和共享来自相同虚拟页面的块成为简单的事情。而且,高速缓存无需处理保护的问题,因为访问权限的检查是地址翻译过程中一部分。
- 利用TLB加速地址翻译:
- 在
MMU
中包括一个关于PTE
的小的缓存,称为TLB
。TLB
是一个小的,虚拟寻址的缓存,其中每一行都保存着一个由单个PTE
组成的块。
- 在
- 多级页表:
- 多级页表——采用层次结构,用来压缩页表。
储存器映射
-
共享对象和私有对象
- 共享对象
- 私有对象于`execve`函数: enter description here
-
使用
mmap
函数的用户级存储器映射:
- 创建新的虚拟存储器区域#include <unistd.h> #include <sys/mman.h> void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-
参数含义:
-start
:这个区域从start开始
-fd
:文件描述符
-length
:连续的对象片大小
-offset
:距文件开始处的偏移量
-prot
:访问权限位,具体如下:
PROT_EXEC:由可以被CPU执行的指令组成
PROT_READ:可读
PROT_WRITE:可写
PROT_NONE:不能被访问
-flag
:由描述被映射对象类型的位组成,具体如下:
MAP_ANON:匿名对象,虚拟页面是二进制0
MAP_PRIVATE:私有的、写时拷贝的对象
MAP_SHARED:共享对象 -
删除虚拟存储器:
#include <unistd.h> #include <sys/mman.h> int munmap(void *start, size_t length); 成功返回0,失败返回-1 从`start`开始删除,由接下来`length`字节组成的区域。
动态存储器分配的方法
-
malloc
和free
函数:-
malloc
函数:从堆中分配块:#include <stdlib.h> void *malloc(size_t size);
-
free
函数:释放已分配的堆块:#include <stdlib.h> void free(void *ptr);
-
-
碎片:分为内部碎片和外部碎片
-
放置策略:首次适配、下一次适配、最佳适配
-
申请额外的堆存储器:
-
sbrk
函数:#include <unistd.h> vid *sbrk(intptr_t incr);
成功则返回旧的
brk
指针,出错为-1通过将内核的
brk
指针增加incr
来扩展和收缩堆。 -
-
实现简单的分配器:序言块和结尾块
-
显式空闲链表的区别
-
分配时间
隐式:分配时间是块总数的线性时间
显式:分配时间是空闲块数量的线性时间。
-
链表形式
隐式:隐式空闲链表
显式:双向链表,有前驱和后继,比头部脚部好使。
-
垃圾收集
- 基本知识:垃圾收集器
Mark&Sweep
垃圾收集器:-
两个阶段:标记、清除
-
相关函数:
ptr定义为typedef void *ptr ptr isPtr(ptr p):如果p指向一个已分配块中的某个字,那么就返回一个指向这个块的起始位置的指针b,否则返回NULL int blockMarked(ptr b):如果已经标记了块b,那么就返回true int blockAllocated(ptr b):如果块b是已分配的,那么久返回ture void markBlock(ptr b):标记块b int length(ptr b):返回块b的以字为单位的长度,不包括头部 void unmarkBlock(ptr b):将块b的状态由已标记的改为未标记的 ptr nextBlock(ptr b):返回堆中块b的后继
-
- C保守的
Mark&Sweep
——平衡二叉树:根本原因是C语言不会用类型标记来标记存储器位置。
C语言中与存储器有关的错误
- 间接引用坏指针:
scanf
错误 - 读未初始化的存储器:假设堆存储器被初始化为0
- 允许栈缓冲区溢出:缓冲区溢出错误
- 假设指针和它们指向的对象是相同大小的
- 造成错位错误
- 引用指针,而不是它所指向的对象
- 误解指针运算
- 引用不存在的变量
- 引用空堆块中的数据
- 引起存储器泄露
本周代码托管链接
教材学习中的问题和解决过程
- 问题1:Linux缺页异常处理的方法
碎片:虽然有未使用的存储器,但是不能用来满足分配请求。 内部碎片:发生在一个已分配块比有效载荷大的时候,易于量化。 外部碎片:发
生在当空闲存储器合计起来足够满足一个分配请求,但是没有一个单独的空间块足以处理这个请求时发生。难以量化,不可预测。
-
问题2:练习题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
-
问题3:为什么将虚拟地址后半部分直接和物理页号串联起来就得到了物理地址?
- 未解决,还是不太明白
-
问题4:这个问题我也不知道怎么解决
- 最后一节C程序中常见的与存储器有关的错误,看完之后就不禁回想起自己在编程的时候遇到的类似的问题。每次遇到这种问题的解决的方法都是去百度,然后根据百度上大家五花八门的方法一个一个试,问题解决了就解决了,没解决便手足无措,错误也不知道具体是由于什么原因而导致的,就很迷茫的那种感觉,感觉自己不会学习吧,没有培养好自己的学习方法。
其他(感悟、思考等,可选)
- 这章是关于虚拟存储器的,这是计算机的一个重要的抽象,从而将计算机中的物理存储空间抽象了出来。
- 当然这也可能引发一些错误,例如上面所说到的c语言中的一些错误,在了解了这些知识后能够更好地帮助我们去避免一些因为存储而出现的错误
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 22/60 | |
第四周 | 600/1300 | 4/9 | 30/90 | |
第五周 | 650/1300 | 5/9 | 40/90 | |
第六周 | 700/1300 | 6/9 | 50/90 | |
第七周 | 800/1300 | 7/9 | 60/90 | |
第八周 | 1200/1700 | 8/10 | 80/110 | |
第九周 | 1800/2000 | 9/11 | 100/120 | |
第十一周 | 2400/3000 | 10/15 | 120/140 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
-
计划学习时间:12小时
-
实际学习时间:18小时
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)