物理和虚拟寻址
-
物理寻址
- CPU访问内存最自然的方式就是使用物理寻址
- 早期的PC使用物理寻址
-
虚拟寻址
- CPU通过生成一个虚拟地址(VA)来访问主存
-
内存管理单元MMU
- 利用存放在主存中的查询表来动态将虚拟地址翻译成物理地址
地址空间
-
地址空间是非负整数地址的有序集合
-
地址空间的大小是由表示最大地址所需要的位数来描述的,2的幂次
虚拟内存作为缓存的工具![在这里插入图片描述](https://img-blog.csdnimg.cn/20210707202502108.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2ODAyNzEz,size_16,color_FFFFFF,t_70#pic_center)
-
虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组
-
VM通过将虚拟内存分割为虚拟页(VP)
-
物理内存被分割为物理页(PP),大小为页帧
-
虚拟页存储在磁盘上,物理页缓存在DRAM中
-
虚拟页面集合分为三个不相交的子集
-
未分配的
- VM系统还未分配或创建的页,未分配的块不占用任何磁盘空间
-
缓存的
- 当前缓存已经在物理内存中的已分配页
-
未缓存的
- 未缓存在物理内存中的已分配页
-
-
页表
-
页表存放在物理内存中
-
页表将虚拟页映射到物理页
-
每次地址翻译硬件将一个虚拟地址转换为物理地址时,都会读取页表
-
操作系统负责维护页表内容,以及在磁盘与DRAM之间来回传送页
-
页表就是一个PTE(页表条目)的数组,每个PTE是由一个有效位和一位地址字段组成
-
有效位
-
如果设置了有效位,那么地址字段就表示DRAM中相应的物理页的起始位置,这个物理页中缓存了该虚拟页
-
如果未设置有效位
- 空地址表示这个虚拟页还没有被分配
- 否则这个地址就指向该虚拟页在磁盘上的起始位置
-
-
-
缺页
-
缺页前
-
DRAM缓存不命中称为缺页(page default)
-
缺页异常调用内核中的缺页异常处理程序,该程序会选择一个“牺牲页“;牺牲页的选择,即被缓存到物理内存上的虚拟页。如果该牺牲页已经被修改,内核会将它复制回磁盘,并修改PTE(页表条目);接下来内核从磁盘复制缺页的虚拟内存,并将其缓存到物理内存中(此过程称称为按需页面调度)
-
按需页面调度
-
调度策略
-
当有不命中发生时,才换入页面的这种策略
-
-
页从磁盘换入DRAM,从DRAM换出磁盘
-
-
页面调度/交换
- 在磁盘和内存之间传送页的活动
-
局部性
- 保证了在任意时刻,程序将取向于在一个较小的活动页面集合上工作,这个集合叫作工作集
-
抖动
- 如果工作集超出了物理内存的大小,那么程序将产生一种状态叫作抖动
虚拟内存作为内存管理的工具
-
操作系统为每个进程提供了一个独立的页表
-
多个虚拟页面可以映射到同一个共享物理页面上
-
内存映射
- 将一组连续的虚拟页映射到任意一个文件中的任意位置
虚拟内存作为内存保护的工具
- 提供独立的地址空间区分不同进程的私有内存,可以在PTE上添加一些额外的许可位控制,如运行内核模式、只可读、只可写
地址翻译
-
多级页表
-
多级页表从两个方面减少了内存要求
- 1)如果一级页表中的一个PTE是空的,那么相应的二级页表就根本不会存在。这代表着一种巨大的潜在节约。
- 只有一级页表才需要总是在主存中;虚拟内存系统可以需要时创建、页面调出或调出二级页表,这就减少了主存的压力;只有最经常使用的二级页表才需要缓存在主存中
-
-
利用TLB加速地址翻译
-
TLB内部结构
-
TLB(翻译后备缓冲器),是一个小的、虚拟寻址的缓存,其中每一行都保存着一个由单个PTE组成的块
-
TLB避免了每次CPU产生一个虚拟地址,MMU就必须查阅一个PTE以便将虚拟地址翻译成物理地址的情况
-
Linux进程的虚拟内存
碎片
-
碎片
- 造成堆利用率很低的主要原因是一种称为碎片的现象,当虽然有未使用的内存但不能用来满足分配请求时,就会发生这种现象
-
内部碎片
- 内部碎片是在一个已分配块比有效载荷大时发生的
-
外部碎片
- 外部碎片是当空闲内存合计起来足够满足一个分配请求,但是没有一个单独的空闲块足够大来处理这个请求的发生
垃圾收集
-
垃圾收集器是一种动态内存分配器
-
垃圾收集器将内存视为一张有向可达图
-
垃圾收集器的角色是维护可达图的某种表示,并通过释放不可达节点且将它们返回给空闲链表,来定期低回收它们
-
Mark&Sweep垃圾收集器
-
标记阶段
- 标记出根节点所有可达的和已分配的后继
-
清除阶段
- 释放每个未被标记的已分配块
-
块头部中空闲的低位中的一位通常用来表示这个块是否被标记了
-