2017-2018-1 20155201 《信息安全系统设计基础》第十一周学习总结
教材学习内容总结
- 地址空间
- 使用虚拟寻址方式时,CPU生成一个虚拟地址访问主存,虚拟地址转换成对应的物理地址。
- 虚拟地址空间:CPU从一个有
N=2^n
个地址的地址空间中生成虚拟地址。- 物理地址空间与系统中物理存储器的M个字节对应。
- 虚拟存储器
- 虚拟存储器是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每个进程提供了一个大的、一致的和私有的地址空间。通过一个很清晰的机制。
- 虚拟存储器将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据;它为每个进程提供了一致的地址空间;它保护了每个进程的地址空间不被其他进程破坏。
- 虚拟存储器被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。
- 假设有一个单独的页表,将虚拟地址空间映射到物理地址空间。操作系统为每个进程提供了一个独立的页表,也是一个独立的虚拟地址空间。
- VM系统通过将虚拟存储器分割为虚拟页来处理较低层作为较高层之间的传输单元这样的问题。
- 在任意时刻,虚拟页面的集合都分为三个不相交的子集:未分配,缓存的,未缓存的。
- 按需页面调度和独立的虚拟地址空间结合,对系统中存储器的使用和管理造成了深远的影响。VM简化了链接、加载、代码和数据共享,以及应用程序的存储器分配。
- 地址翻译:一个N元素的虚拟地址空间(VAS)中的元素和一个M元素的物理地址空间(PAS)中元素之间的映射。
- CPU中的页表基址寄存器指向当前页表。MMU利用VPN来选择适当的PTE。将页表条目中的物理页号和虚拟地址中的虚拟页面偏移串联起来,就得到相应的物理地址。
Intel core i7存储器系统
- 处理器包 包括四个核、一个L3高速缓存,DDR3存储器控制器。每个核包含一个层次结构的TLB、一个层次结构的数据和指令高速缓存,以及一组快速的点到点连接。TLBT是虚拟寻址的,四路组相连的。L1、L2、L3高速缓存是物理寻址的,是八路组相连的。
Linux虚拟存储器系统
- Linux将虚拟存储器组织成一些区域(也叫做段)的集合。一个区域(area)就是已经存在着的(已分配的)虚拟存储器的连续片(chunk),这些页是以某种方式相关联的每个存在的虚拟页面保存在某个区域中,而不属于某个区域的虚拟页是不存在的,并且不能被进程引用。
- 一个具体区域的区域结构包含字段
vm_start:指向这个区域的起始处vm_end:指向这个区域的结束处vm_prot:描述这个区域内包含的所有页的读写许可权限vm_flags:描述这个区域内的页面是与其他进程共享还是私有的。vm_next:指向链表中下一个区域结构。
- 存储器映射
- Linux通过将一个虚拟存储器区域与一个磁盘上的对象关联起来,以初始化这个虚拟存储器区域的内容,这个过程成为存储器映射。虚拟存储器区域可以映射到两种类型的对象中的一种:Unix文件系统中的普通文件匿名文件(由内核创建的)。
- Unix进程可以使用mmap函数来创建新的虚拟存储器区域,并将对象映射到这些区域中。
#include
#include void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); //成功时则返回指向映射区域的指针,出错则为-1 - 动态存储器分配
- 需要额外的虚拟存储器时,使用一种动态存储器分配。一个动态存储器分配器维护着一个进程的虚拟存储器区域,称为堆。对于每个进程,内核维护着一个变量(brk)break,指向堆的顶部。
- 分配器将堆视为一组不同大小的块的集合来维护。每个块就是一个连续的虚拟存储器组块。
教材学习中的问题和解决过程
- 问题1:如何理解fork函数如何创建一个带有自己独立虚拟地址空间的新进程?
- 问题1解决方案:当fork函数被当前进程调用时,内核为新进程创建各种数据结构,并分配给它一个唯一的PID。他创建了当前进程的mm_struct、区域结构和页表的原样拷贝。当fork在新进程中返回的时候,新进程现在的虚拟存储器刚好和调用fork时存在的虚拟存储器相同。当这两个进程中的任一个后来进行写操作时,写时拷贝机制就会创建新页面,因此,也就为每个进程保持了私有地址空间的抽象概念。
- 问题2:之前我们了解到,exev()函数调用完后另一个进程,不会再回到本身的进程,这是为什么?
- 问题2解决方案:加载并运行被exev函数所调用的进程时需以下几个步骤
- 删除已存在的用户区域。删除当前进程虚拟地址用户部分中的已存在的区域结构。- 映射私有区域。为新程序的文本、数据、bss和栈区域创建新的区域结构。所有这些新的区域都是私有的、写时拷贝的。文本和数据区域被映射为a.out文件中的文本和数据区。bss区域是请求二进制零的,映射到匿名文件,其大小包含在a.out中。栈和堆区域也是请求二进制零的。- 映射共享区域。如果a.out程序与共享对象(或目标)链接,比如标准C库libc.so,那么这些对象都是动态链接到这个程序的,然后再映射到用户虚拟地址空间中的共享区域内。- 设置程序计数器(PC)。execve做的最后一件事情就是设置当前进程上下文中的程序计数器,使之指向文本区域的入口点。下一次调度这个进程时,它将从这个入口点开始执行。Linux将根据需要换入代码和数据页面。
Linux根据需要换入代码和数据页面:
代码调试中的问题和解决过程
- 问题1:栈缓冲区溢出是什么意思?
- 问题1解决方法:一个程序不检查输入串的大小就写入栈中的目标缓冲区,那么这个程序就会有缓冲区溢出错误。
void bufoverflow(){ char buf[64]; gets(buf); //gets函数拷贝一个任意长度的串到缓冲区。 return ; }
如何修改?
void bufoverflow(){ char buf[64]; fgets(buf); //fgets函数限制了输入串的大小 return ;}
- 问题2:存储器泄露是什么意思?
- 问题2解决方案:当程序没有释放已分配块的时候,就会存储器泄露。
void leak(int n){ int *x= (int *)Malloc(n * sizeof(int)); return ; //x没有释放就返回了函数 }
如果反复调用leak()函数,那么堆里就会慢慢充满垃圾,会占用整个虚拟地址空间。
结对及互评
本周结对学习情况
结对学习内容
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 195/195 | 1/1 | 10/10 | |
第三周 | 314/706 | 1/2 | 15/25 | |
第五周 | 254/960 | 1/3 | 10/35 | |
第七周 | 24/1759 | 1/4 | 15/50 | |
第九周 | 1207/2966 | 2/6 | 15/65 | |
第十一周 | 147/3113 | 2/8 | 20/85 |
计划学习时间:15小时
实际学习时间:20小时