第九章 虚拟内存

物理地址和虚拟地址:

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

原文地址:https://www.cnblogs.com/sunnyDream/p/10262138.html

时间: 2024-11-13 08:46:21

第九章 虚拟内存的相关文章

第九章 虚拟内存管理

思维导图 虚拟内存 背景: 解决的办法: 常规存储器的特征 一次性和驻留性是必要的吗? 局部性原理(locality of reference) 出现局部性规律的原因: 局部性表现为: 虚拟内存 示意图: 虚拟存储器的特征 请求调页 实现虚拟存储器要解决: 页面调入策略 请求调页 对进程页表的修改 缺页中断的支持 请求页面中的硬件支持 其中各字段说明 缺页中断机构 示意图: 主要动作 缺页率 页面调换 页面置换算法 一般用缺页率来衡量好坏 算法种类 最佳算法 先进先出置换算法 最近最久未使用算法

第九章 引用

第九章 引用 1.  什么是引用? 引用就是别名.int &ra=a;此处的&不是取址运算符,而是引用运算符 3.  引用就是别名常量 4.  引用对象 只能 int &ra=a;// 注意定义引用时要对其初始化 int &ra; ra=a;  //这样是错误的,引用就像常量,只能初始化不能赋值 对象也可以定义一个引用,但是类不能,因为它没有具体的内存地址 5.  空引用 6.  按值传递 按值传递(传递的是副本)≠按地址传递()≠按别名传递(有什么不同?) 9.1.利用指

javascript高级程序设计 第九章-- 客户端检测

javascript高级程序设计 第九章-- 客户端检测 客户端检测是javascript开发中最具争议的一个话题,由于浏览器间存在差别,通常需要根据不同浏览器的能力分别编写不同的代码.有下列常使用的客户端检测方法:能力检测:在编写代码之前先检测特定浏览器的能力.例如,脚本在调用某个函数之前,可能要先检测该函数是否存在.这种检测方法将开发人员从考虑具体的浏览器类型和版本中解放出来,让他们把注意力集中到相应的能力是否存在上.能力检测无法精确地检测特定的浏览器和版本.怪癖检测:怪癖实际上是浏览器中存

zabbix专题:第九章 自定义key(案例:监控内存,监控nginx状态)

第九章 自定义key 对Linux有兴趣的朋友加入QQ群:476794643 在线交流 本文防盗链:http://zhang789.blog.51cto.com 为什么要自定义KEY 有时候我们想让被监控端执行一个zabbix没有预定义的检测,zabbix的用户自定义参数功能提供了这个方法.我们可以在客户端配置文件zabbix_angentd.conf里面配置UserParameter. 语法如下: UserParameter=key,command 用户自定义参数包含一个key和一个命令,ke

操作系统思考 第三章 虚拟内存

第三章 虚拟内存 作者:Allen B. Downey 原文:Chapter 3 Virtual memory 译者:飞龙 协议:CC BY-NC-SA 4.0 3.1 简明信息理论 比特是二进制的数字,也是信息的单位.一个比特有两种可能的情况,写为0或者1.如果是两个比特,那就有四种可能的组合,00.01.10和11.通常,如果你有b个比特,你就可以表示2 ** b个值之一.一个字节是8个比特,所以它可以储存256个值之一. 从其它方面来讲,假设你想要储存字母表中的字母.字母共有26个,所以你

读书笔记第九章

第九章HAL是建立在linux驱动之上的一套程序库.这套程序库并不属于linux内核,而是属于linux内核层之上的应用层.可以用来保护不想公开源代码的作者.HAL架构比较简单,其基本原理就是在安卓系统中使用程序库调用位于内核空间的linux驱动,然后安卓应用程序可以通过NDK程序访问HAL中的程序库,或直接在安卓应用程序中访问HAL中的程序库.编写一款支持HAL的linux驱动程序的步骤:1.编写linux驱动,linux驱动的代码要尽量简介,尽可能将业务逻辑放到HAL library中.2.

第九章 两种模式的比较

#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include

第九章 用多线程来读取epoll模型下的客户端数据

#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include

第九章 TCP和UDP同时用复用一个端口实现一个回射服务器

#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include