虚拟存储器的三个重要功能:
物理寻址:主存被组织成一个由M个连续的字节大小的单元组成的数组,依次类推的寻址方式称为物理寻址。
虚拟寻址:CPU生成一个虚拟地址(VA)来访问主存,在被传送到存储器之前先转换成适当的物理地址。地址翻译通过CPU芯片上的存储器管理单元完成。
地址空间是一个非负整数地址的有序集合:
{0,1,2,......}
VM系统将虚拟存储器分割为虚拟页,虚拟页面的集合分为三个不相交的子集:
页表:将虚拟页映射到物理页,就是一个页表条目的数组。
PTE:由一个有效位和一个n位地址字段组成的,表明了该虚拟页是否被缓存在DRAM中。
当CPU读取一个字的时候,地址翻译硬件将虚拟地址作为一个索引来定位PTE,并从存储器中读取它。
DRA缓存不命中称为缺页。在不命中发生时,换入页面的策略称为按需页面调度。
地址翻译是一个N元素的虚拟地址空间(VAS)中的元素和一个M元素的物理地址空间(PAS)之间的映射。
MAP:VAS→PAS∪空
MAP(A)=
CPU中的一个控制寄存器页表基址寄存器指向当前页表,n位的虚拟地址包含两个部分:一个p位的虚拟页面偏移(VPO) 和一个(n-p)位的虚拟页号,页表条目中的物理页页号和虚拟地址中的VPO串联起来,就得到了相应的物理地址。
在MMU中包括了一个关于PTE的小的缓存,称为翻译后备缓冲器(TLB),其中每一行都保存着一个由单个PTE组成的块。
用来压缩页表的常用方法是使用层次结构的页表。
Linux通过将一个虚拟存储器区域与一个磁盘上的对象关联起来,以初始化这个虚拟存储器区域的内容,这个过程成为存储器映射。具体可以映射的对象有两种:
一旦一个虚拟页面被初始化了,它就在一个由内核维护的专门的交换文件之间换来换去。交换文件也叫交换空间,或交换区域。
一个对象被映射到虚拟存储器的一个区域,要么作为共享对象,要么作为私有对象。
一个映射到共享对象的虚拟存储器区域叫做共享区域,类似的,也有虚拟区域。
私有对象时使用一种叫做写时拷贝的技术被映射到虚拟存储器中的,相应私有区域的页表条目都被标记为只读,并且区域结构被标记为私有的写时拷贝。
使用execve函数将a.out程序加载到存储器的过程
Execve("a.out",NULL,NULL);
具体经过的步骤如下:
设置程序计数器。
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.
当运行时需要额外虚拟存储器时,使用动态存储器分配器维护一个进程的虚拟存储器区域。分配器有两种风格。
显示分配器:要求应用显式地释放任何已经分配的块。
隐式分配器:要求分配器检测一个已分配块何时不再被程序所使用,就释放这个块。也叫做垃圾收集器。
C标准库提供了一个称为malloc程序包的显式分配器,程序通过调用malloc函数来从标准堆中分配块。
void *malloc(size_t size); 若成功则为指针,若出错则为NULL。
通过调用free函数来释放已分配的块。
void free(void *ptr);
显式分配器工作的约束条件:
理想分配器的目标:
垃圾收集器是一种动态存储分配器。,自动释放程序已经不再需要的已分配快(垃圾)。
垃圾收集器将存储器视为一张有向可达图,图的节点被分配为一组根节点和一组堆节点。当存在一条从任意根节点出发到并到达P的有向路径时,就称节点P是可达的。
Mark&Sweep垃圾收集器由标记阶段和清除阶段组成,标记阶段标记出根节点所有可达的和已分配的后继,清除阶段释放每个未被标记的已分配块。
在对Mark&Sweep的描述中使用下列函数
间接引用坏指针:在进程的虚拟地址空间中有较大的洞,没有映射到任何有意义的数据,如果试图引用一个指向这些洞的指针,操作系统就会以段异常来终止程序。典型的错误是:
scanf("%d",val);
读未初始化的存储器:虽然bass存储器位置总是被加载器初始化为0,但对于堆存储器却并不是这样的。
允许栈缓冲区溢出:如果一个程序不检查输入串的大小就。写入栈中的目标缓冲区,程序就会出现缓冲区溢出错误。
假设指针和指向他们的对象大小是相同的。
造成错位错误。
引用指针,而不是他所指向的对象。
误解指针运算:忘记了指针的算术操作是以它们指向的对象的大小为单位来进行,而这种大小单位不一定是字节。
引用不存在的变量。
引用空闲堆块中的数据。
引起存储器泄露:当不小心忘记释放已分配块,而在堆里创建了垃圾时,就会引起存储器泄露。