• 第九章 虚拟内存


    物理地址和虚拟地址:

    计算机的主存被组织成一个由M个连续的字节大小的单元组成的数组。每个字节都有一个唯一的物理地址(PA)。第一个字节地址为0,接下来为1,再接下来为2,依次类推。CPU访问内存的最自然方式就是使用物理地址。我们把这种方式称为物理寻址。如图所示。

                                                                                                        

     现代处理器使用一种称为虚拟地址的寻址方式。使用虚拟寻址,CPU通过生成一个虚拟地址(VA)来访问主存,这个虚拟地址在被送到内存之前先准换成适当的物理地址。将一个虚拟地址转换成物理地址的任务叫做地址翻译。CPU上通过内存管理单元这个专用硬件,利用存放在主存中的查询表来动态翻译虚拟地址,该表的内容由操作系统管理。

                                                                                    

    地址空间

    地址空间是一个非负整数地址的有序集合。如果地址空间中的整数是连续的,那么我们说它是一个线性的地址空间。在一个带虚拟内存的系统中,CPU从一个有N=2^n 个地址的地址空间中生成虚拟地址,这个地址空间称为虚拟地址空间。一个地址空间的大小由表示最大地址所需要的位数来描述。例如一个N=2^n 个地址的虚拟地址空间就叫做一个n位地址空间,现代操作系统通常支持32位和64位虚拟地址空间。

    虚拟内存作为缓存的工具

    概念上而言,虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。每个字节都有唯一的虚拟地址,作为数组的索引。磁盘上数组的内容被缓存在主存中。和存储器层次结构中其他缓存一样,磁盘上(较低层)的数据被分割成块,这些块作为磁盘和主存(较高层)之间的传输单元。VM系统通过将虚拟内存分割成为虚拟页(Virtual Page,VP),每个虚拟页的大小为P = 2^p字节。类似的物理内存也被分割成为物理页(Physical Page,PP),大小也是P字节(物理页也被成为页帧)

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

    1、未分配的:VM系统还未分配(或者创建)的页。未分配的块没有任何数据和它们相互关联,因此也不占用任何磁盘空间。

    2、缓存的:当前已缓存在物理内存中已分配的页

    3、未缓存:未缓存在物理内存中的已分配页

                                                                                     

    垃圾收集

    在诸如C malloc包这样的显示分配器中,应用通过调用malloc和free来分配和释放堆块。应用要负责释放所有不再需要的已分配块。

    未能释放已分配的块是一种常见的编程错误。

    垃圾收集器是一种动态内存分配器,它自动释放程序不再需要的已分配块。这些块被称为垃圾。自动回收堆存储的过程叫做垃圾收集。

    垃圾收集器可以将内存视为一张有向可达图,该图的节点被分为一组根节点和一组堆节点,每个堆节点对应于堆中的一个已分配块。根节点对应于这样一种不在堆中的位置,它们中包含指向堆中的指针。这些位置可以是寄存器、栈里的变量、或者是虚拟内存中读写数据区域内的全局变量。

    当存在一条从任意根节点出发并到达p的有向路径时,我们可以说节点p是可达的。在任何时刻,不可达节点对应于垃圾,是不能被应用再次使用的。垃圾收集器的角色是维护可达图的某种表示,并通过释放不可达节点且将它们返回给空闲链表,来定期回收它们。

    Mark&Sweep垃圾收集器

    MarkSweep垃圾收集器由标记阶段和清除阶段组成,标记阶段标记出根节点的所有可达的和已分配的后继,而后面的清除阶段释放每个未被标记的已分配块。块头部中空闲的低位中的一位通常用来表示这个块是否被标记。

    假设初始情况下,一个堆由六个已分配块组成,其中每个块都是未分配的。第三个块包含一个指向第一个块的指针。第四个块包含指向第三个块和第六个块的指针。根指向第四个块,在标记阶段之后,第一个快、第三个块、第四个块和第六个块都做了标记,因为它们是从根节点可达的。第二块和第五块是未标记的,因为它们是不可达的。在清除节点之后,这两个不可达块被回收到空闲链表。

    C程序中常见的与内存相关的错误

    对于C程序员来说,管理和使用虚拟内存是一件困难和容易出错的任务。常见的错误示例包括:间接引用坏指针,读取未初始化的内存,允许栈缓冲区溢出。假设指针和它们指向的对象大小相同,引用指针而不是它所指向的对象,误解指针运算,引用不存在的变量以及引起内存泄漏。

  • 相关阅读:
    View相关知识学习总结
    关于Android四大组件的学习总结
    Android开发框架--AndroidAnnotations(一)
    USACO 3.4
    hdu 2723
    hdu 2721
    hdu 2719
    hdu 1527
    hdu 1260
    hdu 2603
  • 原文地址:https://www.cnblogs.com/sunnyDream/p/10262138.html
Copyright © 2020-2023  润新知