协会工作方案网站建设困难,比较权威的房产网站,自己做网站怎么上传到网上,公司网站建设需要些什么要求第九章 虚拟存储器 虚拟存储器是计算机系统最重要的概念之一#xff0c;它是对主存的一个抽象 三个重要能力#xff1a; 它将主存看成是一个存储在磁盘上的地址空间的高速缓存#xff0c;在主存中只保存活动区域#xff0c;并根据需要在磁盘和主存之间来回传送数据#xf…第九章 虚拟存储器 虚拟存储器是计算机系统最重要的概念之一它是对主存的一个抽象 三个重要能力 它将主存看成是一个存储在磁盘上的地址空间的高速缓存在主存中只保存活动区域并根据需要在磁盘和主存之间来回传送数据通过这种方式高效的使用了主存它为每个进程提供了一致的地址空间从而简化了存储器管理它保护了每个进程的地址空间不被其他进程破坏第一节 物理和虚拟寻址 1.物理地址 计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组每字节都有一个唯一的物理地址PA。 根据物理地址寻址的是物理寻址。 2.虚拟地址 虚拟存储器被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。 使用虚拟寻址时CPU通过生成一个虚拟地址VA来访问主存这个虚拟地址在被送到存储器之前先转换成适当的物理地址 第二节 地址空间 1.地址空间 地址空间是一个非负整数地址的有序集合 {0,1,2,……} 2.线性地址空间 地址空间中的整数是连续的。 3.虚拟地址空间 CPU从一个有 N2^n 个地址的地址空间中生成虚拟地址这个地址空间成为称为虚拟地址空间。 4.地址空间的大小 由表示最大地址所需要的位数来描述。 N2^nn位地址空间 主存中的每个字节都有一个选自虚拟地址空间的虚拟地址和一个选自物理地址空间的物理地址。 第三节 虚拟存储器作为缓存的工具 虚拟存储器——虚拟页VP每个虚拟页大小为P2^平字节 物理存储器——物理页PP也叫页帧大小也为P字节。 1.DRAM缓存的组织结构 2.页表 3.缺页 4.虚拟存储器中的局部性 第四节 虚拟存储器作为存储器管理的工具 操作系统为每个进程提供了一个独立的页表也就是一个独立的虚拟地址空间。抖个虚拟页面可以映射到同一个共享物理页面上。存储器映射将一组连续的虚拟页映射到任意一个文件中的任意位置的表示法。VM简化了链接和加载、代码和数据共享以及应用程序的存储器分配。 第五节 虚拟存储器作为存储器保护的工具 这里需要知道PTE的三个许可位 SUP表示进程是否必须运行在内核模式下才能访问该页READ读权限WRITE写权限第六节 地址翻译 具体符号见上图 地址翻译就是一个N元素的虚拟地址空间VAS中的元素和一个M元素的物理地址空间PAS中元素之间的映射。 页面基址寄存器PTBR指向当前页表。 MMU利用VPN选择适当的PTE。 PPOVPO。 1.当页面命中时CPU动作 处理器生成虚拟地址传给MMUMMU生成PTE地址并从高速缓存/主存请求得到他高速缓存/主存向MMU返回PTEMMU构造物理地址并把它传给高速缓存/主存 高速缓存/主存返回所请求的数据给处理器。 2.处理缺页时 处理器生成虚拟地址传给MMUMMU生成PTE地址并从高速缓存/主存请求得到他高速缓存/主存向MMU返回PTEPTE中有效位为0触发缺页异常确定牺牲页调入新页面更新PTE 返回原来的进程再次执行导致缺页的指令会命中 一、结合高速缓存和虚拟存储器来看 首先在既使用SRAM高速缓存又使用虚拟存储器的系统中大多数系统选择物理寻址主要思路是地址翻译发生在高速缓存之前页表目录可以缓存就像其他的数据字一样二、利用TLB加速地址翻译 TLB翻译后备缓冲器是一个小的、虚拟存储的缓存其中每一行都保存着一个由单个PTE组成的块 步骤 CPU产生一个虚拟地址MMU从TLB中取出相应的PTEMMU将这个虚拟地址翻译成一个物理地址并且将它发送到高速缓存/主存高速缓存/主存将所请求的数据字返回给CPU三、多级页表 多级页表——采用层次结构用来压缩页表。 1.以两层页表层次结构为例好处是 如果一级页表中的一个PTE是空的那么相应的二级页表就根本不会存在只有一级页表才需要总是在主存中虚拟存储器系统可以在需要时创建、页面调入或调出二级页表只有最经常使用的二级页表才缓存在主存中。2.多级页表的地址翻译 四、端对端的地址翻译 这一部分看懂书上的例题。 第七节 案例研究 一、Core i7地址翻译 在这里PTE有三个权限位 R/W位确定内容是读写还是只读U/S位确定是否能在用户模式访问该页XD位禁止执行位64位系统中引入可以用来禁止从某些存储器页取指令还有连个缺页处理程序涉及到的位 A位引用位实现页替换算法D位脏位告诉是否必须写回牺牲页二、Linux虚拟存储器系统 Linux为每个进程维持了一个单独的虚拟地址空间如图 内核虚拟存储器包括内核中的代码和数据结构。 一部分区域映射到所有进程共享的物理页面 另一部分包含每个进程都不相同的数据。 一、Linux虚拟存储器区域 区域就是已分配的虚拟存储器的连续片。 区域的例子 代码段数据段堆共享库段用户栈……每个存在的虚拟页面都保存在某个区域中。内核为系统中的每个进程维护一个单独的任务结构task_struct 一个具体区域的区域结构包括 vm_start指向起始处vm_end指向结束处vm_prot描述这个区域包含的所有页的读写许可权限vm_flags是共享的还是私有的vm_next指向下一个区域二、Linux缺页异常处理 1.虚拟地址A是否合法 不合法触发段错误终止进程 合法进入下一条 2.存储器访问是否合法即是否有权限 不合法触发保护异常终止程序 合法进入下一条 3.这时是针对合法的虚拟地址进行合法的操作。所以选择一个牺牲页面如果被修改过就换新的并更新页表。 第八节 存储器映射 即指Linux通过将一个虚拟存储器区域与一个磁盘上的对象关联起来以初始化这个虚拟存储器区域的内容的过程。 映射对象 1.Unix文件系统中的普通文件 2.匿名文件全都是二进制0 一、共享对象和私有对象 1.共享对象 共享对象对于所有把它映射到自己的虚拟存储器进程来说都是可见的 即使映射到多个共享区域物理存储器中也只需要存放共享对象的一个拷贝。 2.私有对象 私有对象运用的技术写时拷贝在物理存储器中只保存有私有对象的一份拷贝fork函数就是应用了写时拷贝技术至于execve函数 二、使用mmap函数的用户级存储器映射 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 参数含义 start这个区域从start开始fd文件描述符length连续的对象片大小offset距文件开始处的偏移量 prot访问权限位具体如下 PROT_EXEC:由可以被CPU执行的指令组成
PROT_READ:可读
PROT_WRITE:可写
PROT_NONE:不能被访问 flag由描述被映射对象类型的位组成具体如下 MAP_ANON:匿名对象虚拟页面是二进制0
MAP_PRIVATE:私有的、写时拷贝的对象
MAP_SHARED共享对象 2.删除虚拟存储器 include include sys/mman.h int munmap(void *start, size_t length); 成功返回0失败返回-1 从start开始删除由接下来length字节组成的区域。 第九节 动态存储器分配 1.堆 是一个请求二进制0的区域紧接在未初始化的bss区域后开始并向上更高的地址生长。有一个变量brk指向堆的顶部 2.分配器的两种基本风格 a.显示分配器-malloc和free b.隐式分配器/垃圾收集器 一、malloc和free函数 系统调用malloc函数从堆中分配块 #include stdlib.hvoid *malloc(size_t size); 成功返回指针指向大小至少为size字节的存储器块失败返回NULL 系统调用free函数来释放已分配的堆块 #include stdlib.hvoid free(void *ptr); 无返回值 ptr参数必须指向一个从malloc、calloc或者reallov获得的已分配块的起始位置。 为什么要使用动态存储器分配 因为经常知道程序实际运行时它们才知道某些数据结构的大小。 二、分配器的要求和目标 1.要求 处理任意请求序列立即响应请求只使用堆对齐块不修改已分配的块2.目标 最大化吞吐率吞吐率每个单位时间里完成的请求数最大化存储器利用率——峰值利用率最大化三、碎片 虽然有未使用的存储器但是不能用来满足分配请求时发生这种现象。 1.内部碎片 发生在一个已分配块比有效载荷大的时候 易于量化。 2.外部碎片 发生在当空闲存储器合计起来足够满足一个分配请求但是没有一个单独的空间块足以处理这个请求时发生 难以量化不可预测。 四、隐式空闲链表 堆块的格式 由一个字的头部有效荷载和可能的额外填充组成。 将堆组织成一个连续的已分配块和空闲块的序列 空闲块通过头部中的大小字段隐含地连接着分配器可以通过遍历堆中所有的块从而间接地遍历整个空闲块的集合。 需要特殊标记的结束块。 系统对齐要求和分配器对块格式的选择会对分配器上的最小块大小有强制的要求。 五、放置已分配的块——放置策略 1.首次适配 从头开始搜索空闲链表选择第一个合适的空闲块 2.下一次适配 从上一次搜索的结束位置开始搜索 3.最佳适配 检索每个空闲块选择适合所需请求大小的最小空闲块 六、申请额外的堆存储器 用到sbrk函数 #include unistd.hvid *sbrk(intptr_t incr); 成功则返回旧的brk指针出错为-1 通过将内核的brk指针增加incr来扩展和收缩堆。 七、合并空闲块 合并是针对于假碎片问题的任何实际的分配器都必须合并相邻的空闲块。 有两种策略 立即合并推迟合并八、带边界的合并 这个合并的意思是因为头部的存在所以向后合并是简单的但是向前合并是不方便的所以就在块的最后加一个脚部作为头部的副本就方便了合并具体四种情况如下 空闲块总是需要脚部的。 九、实现简单的分配器 这里课本上给了一个详细的例子关于如何实现一个简单分配器的设计有几点是需要注意的 序言块和结尾块序言块是初始化时创建的而且永不释放结尾块是一个特殊的块总是以它为结束。有一个技巧就是将重复使用的操作复杂又有重复性的这些可以定义成宏方便使用也方便修改。需要注意强制类型转换尤其是带指针的非常复杂。因为规定了字节对齐方式为双字就代表块的大小是双字的整数倍不是的舍入到是。十、显式空闲链表 1.区别 1分配时间 隐式的分配时间是块总数的线性时间 但是显式的是空闲块数量的线性时间。 2链表形式 隐式——隐式空闲链表 显式——双向链表有前驱和后继比头部脚部好使。 2.排序策略 后进先出按照地址顺序维护十一、分离的空闲链表 分离存储是一种流行的减少分配时间的方法。一般思路是将所有可能的块大小分成一些等价类/大小类。 分配器维护着一个空闲链表数组每个大小类一个空闲链表按照大小的升序排列。 有两种基本方法 1.简单分离存储 每个大小类的空闲链表包含大小相等的块每个块的大小就是这个大小类中最大元素的大小。 1操作 如果链表非空分配其中第一块的全部 如果链表为空分配器向操作系统请求一个固定大小的额外存储器片将这个片分成大小相等的块并且连接起来成为新的空闲链表。 2优缺点 优点时间快开销小 缺点容易造成内部、外部碎片 2.分离适配 每个空闲链表是和一个大小类相关联的并且被组织成某种类型的显示或隐式链表每个链表包含潜在的大小不同的块这些块的大小是大小类的成员。 这种方法快速并且对存储器使用很有效率。 3.伙伴系统——分离适配的特例 其中每个大小类都是2的幂 这样给定地址和块的大小很容易计算出它的伙伴的地址也就是说一个块的地址和它的伙伴的地址只有一位不同。 优点快速检索快速合并。 第十节 垃圾收集 垃圾收集器是一种动态存储分配器它自动释放程序不再需要的已分配块这些块被称为垃圾自动回收堆存储的过程叫做垃圾收集。 1.基本知识 垃圾收集器将存储器视作一张有向可达图只有当存在一条从任意根节点出发并到达p的有向路径时才说节点p是可达的而不可达点就是垃圾。 2.MarkSweep垃圾收集器 有两个阶段 标记标记出根节点的所有可达的和已分配的后继清楚释放每个未被标记的已分配块。相关函数 ptr定义为typedef void *ptr ptr isPtr(ptr p)如果p指向一个已分配块中的某个字那么就返回一个指向这个块的起始位置的指针b否则返回NULLint blockMarked(ptr b)如果已经标记了块b那么就返回trueint blockAllocated(ptr b)如果块b是已分配的那么久返回turevoid markBlock(ptr b)标记块bint length(ptr b)返回块b的以字为单位的长度不包括头部void unmarkBlock(ptr b)将块b的状态由已标记的改为未标记的ptr nextBlock(ptr b)返回堆中块b的后继 3.C保守的MarkSweep——平衡二叉树 根本原因是C语言不会用类型标记来标记存储器位置。转载于:https://www.cnblogs.com/nizaikanwoma/p/6195845.html