zoukankan      html  css  js  c++  java
  • 第9章 虚拟存储区(深入理解计算机系统)

    一个系统中的进程是与其他进程共享CPU和主存资源的。为了更加有效地管理存储器并且少出错,现在系统提供了一种对主存的抽象概念,叫做虚拟存储器(VM)。虚拟存储器是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每一个进程提供了一个大的、一致的和私有的地址空间。虚拟存储器提供了三个重要的能力:1)它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,它高效地使用了主存。2)它为每个进程提供了一致的地址空间,从而简化了存储器的管理。3)它保护了每个进程的地址空间不被其他进程破坏。

    9.1 物理和虚拟寻址

    使用虚拟寻址时,CPU通过生成一个虚拟地址(Virtual Address,VA)来访问主存,这个虚拟地址在被送到存储器之前先转换成适当的物理地址。将一个虚拟地址转换为物理地址的任务叫做地址翻译。地址翻译需要CPU硬件和操作系统之间的紧密合作。CPU芯片上叫做存储器管理单元(Memory Management Unit,MMU)的专用硬件,利用存放在主存中的查询表来动态翻译虚拟地址,该表的内容是有操作系统管理的。

    9.2 地址空间

    一个地址空间的大小是由表示最大地址所需要的位数来描述的。一个包含N=2^n个地址的虚拟地址空间就叫做一个n位地址空间。现代操作系统典型的支持32位或者64为虚拟地址空间。一个系统还有一个物理地址空间,它与系统中物理存储器的M个字节相对应。

    9.3虚拟存储器作为缓存的工具

    9.3.1 DRAM缓存的组织结构

    和存储器结构中其他缓存一样,磁盘(较低层)上的数据被分割成块,这些块座位磁盘和主存之间的传输单元。VM系统通过将虚拟存储器分割为称为虚拟页(Virtual Page,VP)的大小固定的块来处理这个问题,大小为P=2^p字节。类似的,物理存储器被分割为物理页(Physical Page,PP),大小也为P字节(物理也也称为页帧(Page Frame))。

    在任意时刻,虚拟页面的集合都分为三个不相交的子集:

    • 为分配的:VM系统还未分配(或者创建)的页。未分配的块没有任何数据和它们相关联,因此也就不占用任何磁盘空间。
    • 缓存的:当前缓存在物理存储器中的已分配页。
    • 未缓存的:没有缓存在物理存储器中的已分配页。

    9.3.2 页表

    页表,将虚拟页映射到物理页,存放在物理存储器中。每次地址翻译硬件将一个虚拟地址转换为物理地址时都会读取页表。操作系统负责维护页表的内容,以及在磁盘与DRAM之间来回传送页。页表就是一个页表条目(Page Table Entry)的数组。虚拟地址空间的每个页在页表中一个固定偏移量处都有一个PTE。每个PTE是由一个有效位和一个n位地址字段组成的。有效位表明了该虚拟页当前是否被缓存在DRAM中。地址字段表示该虚拟页在DRAM中的位置或磁盘上的起始位置。

    9.3.3 页命中

    9.3.4 缺页

    DRAM的缓存不命中称为缺页(page fault)。

    9.8 存储器映射

    Linux通过将一个虚拟存储器区域与一个磁盘上的对象(object)关联起来,以初始化这个虚拟存储器区域的内容,这个过程称为存储器映射(memory mapping)。虚拟存储器可以映射到两种类型的对象中的一种:

    1)Unix文件系统中的普通文件:一个区域可以映射到一个普通磁盘文件的连续部分。

    2)匿名文件:一个区域可以映射到一个匿名文件,匿名文件是由内核创建的,包含的全是二进制零。

    9.9 动态存储器分配

    虽然可以使用低级的mmap和munmap函数来创建和删除虚拟存储器的区域,但是C程序员还是会觉得当运行时需要额外虚拟存储器时,用动态存储器分配器更方便,也有更好的可移植性。

    动态存储器分配器维护着一个进程的虚拟存储器区域,称为堆(heap)。它紧接在未初始化的bss区域后开始,并向上生长(向更高的地址)。对于每个进程,内核维护着一个变量brk,它指向堆的顶部。

    分配器有两种基本风格。两种风格都要求应用显示地分配块。它们的不同在于由哪个实体来负责释放已分配的块。

    显式分配器:要求应用显式地释放任何已分配的块。例如,C标准库提供一种叫做malloc程序包的显式分配器。C程序通过调用malloc函数来分配一个块,并通过调用free函数来释放一个块。C++中用new和delete

    隐式分配器:要求分配器检测一个已分配块何时不再被程序所使用,那么就释放这个块。隐式分配器也叫做垃圾收集器。

    9.9.4 碎片

    造成堆利用率很低的主要原因是一种称为碎片的现象,当虽然有未使用存储器单不能用来满足分配请求时,就会发生这种现象。有两种形式的碎片:内部碎片(internal fragmentation)和外部碎片(external fragmentation)。

    内部碎片是在一个已分配块比有效荷载大时发生的。很多原因都可能造成这个问题,如,一个分配器的实现可能对已分配块强加一个最小的大小值,而这个值比请求的有效荷载大,或者,分配器可能增加块大小以满足对齐约束条件。

    外部碎片是当空闲存储器合计起来足够满足一个分配请求,但是没有一个单独的空闲块足够大可以来处理这个请求时发生的。

  • 相关阅读:
    编译pypcap
    python输出重复字符串的简单办法
    Python天天美味(1) 交换变量(转)
    Python天天美味(4) isinstance判断对象类型(转)
    Python天天美味(2) 字符遍历的艺术(转)
    Python天天美味(3) 字符转换(转)
    Python天天美味(5) ljust rjust center(转)
    Python天天美味(6) strip lstrip rstrip(转)
    Python天天美味(10) 除法小技巧(转)
    Python标准库12 数学与随机数 (math包,random包)(转)
  • 原文地址:https://www.cnblogs.com/cinvzi/p/9369737.html
Copyright © 2011-2022 走看看