虚拟存储器

定义:

对主存的抽象机制,是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互。

功能:

1. 将主存看成是一个存储在磁盘上的地址空间的高速缓存,在内存中只保存活动区域,并根据需要在磁盘和内存之间来回传送数据。

2. 为进程提供了一致的地址空间,从而简化了存储器管理。

3. 保护了每个进程的地址空间不被其他进程所破坏。

9.1 物理和虚拟地址

CPU通过生成一个虚拟地址(Virtual address,VA)来访问主存。将虚拟地址转换为物理地址叫做地址翻译(address translation)。地址翻译也需要CPU硬件和操作系统之间的紧密结合。

CPU芯片上有叫做存储器管理单元(Memory Management Unit,MMU)的专用硬件。利用存储在主存中的查询表来动态翻译虚拟地址。 查询表由操作系统管理。

9.2 地址空间

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

概念上而言,虚拟存储器(VM)被组织为一个存放在磁盘上的N个连续字节大小的单元组成的数组。每个字节都有一个唯一的虚拟地址,这个唯一的虚拟地址作为到数组的索引。磁盘上数组的内容被缓存到主存中。VM系统通过将虚拟存储器分割为称为虚拟页的大小固定的块来处理磁盘和主存信息交互问题。

任何时候,虚拟页的集合都被分为3个不相交的子集。

1、[未分配的] VM系统还未分配(或者创建)的页。未分配的块没有任何数据与之相关联。不占用磁盘空间

2、[缓存的] 当前缓存在物理存储器的已分配页。

3、[未缓存的] 没有缓存在物理页面存储器中的已分配页。

9.3.2 页表

9.4 虚拟存储器作为存储器管理的工具

操作系统为每个进程提供一个独立的页表,VM简化了链接和加载,代码和数据共享,以及应用程序的存储器分配。

1.简化链接

独立的空间地址意味着每个进程的存储器映像使用相同的格式。文本节总是从0x08048000(32位)处

或0x400000(64位)处开始。然后是数据,bss节,栈。一致性极大简化了链接器的设计和实现。

2.简化加载

在ELF可执行文件中.text和.data节是连续的。要把这些节加载到一个新创建的进程中,linux加载器.

分配虚拟页的一个连续的片,从地址0x08048000处(32bit)开始, 或者从0x400000(64bit),

[把这些虚拟页标记为无效,将页表条目指向目标文件中适当的位置,加载器从不实际拷贝任何数据从磁盘到存储器.]

3.简化共享

4.简化存储器分配

malloc在堆空间分配一个适当数字(例如k)个连续的虚拟存储器页面,并且将他们映射到物理存储器中任意

位置的k个任意(不一定连续)的物理页面。

9.5 虚拟存储器作为存储器保护的工具

9.7.2 Linux虚拟存储器系统

Linux为每个进程维持一个单独的虚拟地址空间:内核虚拟存储器和进程虚拟存储器。

内核虚拟存储器包含内核中的代码和数据。

1、内核虚拟存储器的某些区域被映射到所有进程共享的物理页面.如:内核代码,全局数据结构。

2、Linux将一组连续的虚拟页面(大小等同于系统DRAM总量)映射到相应的一组物理页面。[直接映射,不使用页表]

3、内核虚拟存储器包含每个进程不相同的数据。页表,内核在进程上下文中时使用的栈等。

1.Linux 虚拟存储器区域

Linux将虚拟存储器组织成一些区域(也叫做段)的集合。一个区域

就是已经存在着的(已分配的) 虚拟存储器的连续片,这些片/页已某种形式相关联。

如:代码段,数据段,堆,共享库段,用户栈。

所有存在的虚拟页都保存在某个区域,允许虚拟地址空间有间隙。

虚拟存储器区域的内核数据结构

task_struct

mm_struct: 描述了虚拟存储器的当前状态。

pgd: 指向第一级页表的基址。当进程运行时,内核将pgd存放在CR3控制寄存器

mmap: 指向vm_area_structs的链表

vm_area_structs描述了当前虚拟地址空间的一个区域(area).

vm_start:指向这个区域的起始处。

vm_end:指向这个区域的结束处。

vm_port:描述这个区域内包含的所有页的读写许可权限。

vm_flags:描述这个区域页面是否与其他进程共享,还是私有等

vm_next: 指向链表的下一个区域。

2.Linux缺页异常处理

MMU在试图翻译虚拟地址A时,触发缺页。这个异常导致控制转移到缺页处理程序,执行如下步骤:

1、虚拟地址A是合法的吗? A在某个区域结构定义的区域内吗?

解决方法: 缺页处理程序搜索区域结构链表。把A和每个区域的vm_start和vm_end做比较。

如果不合法,触发段错误。

2、试图访问的存储器是否合法? 即:是否有读,写,执行这个页面的权限?

如果不合法,触发保护异常,终止进程。一切正常的话

3、若不存在以上情况,则选择牺牲页,替换,重新执行指令

9.8 存储器映射

定义:

Linux 通过将一个虚拟存储器区域与一个磁盘上的对象关联,以初始化这个虚拟存储器区域的内容。

虚拟存储器区域可以映射到以下两种类型文件:

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

例如,一个可执行文件。文件区(section)被分成页大小的片,每一片包含一个虚拟页面的初始化内容。

仅仅是初始化,虚拟页面此时还并未进入物理存储器,直到CPU第一次引用这个页面。

2、匿名文件

匿名文件由内核创建,包含的全是二进制零。CPU第一次引用这样区域(匿名文件)的虚拟页面时,

将存储器中牺牲页面全部用二进制零覆盖。并将虚拟页面标记为驻留在存储器中。

注意在磁盘和存储器之间并没有实际的数据传送。又叫请求二进制零的页(demand-zero page)。

注意: 一个虚拟页被初始化了,它就在一个有内核维护的专门的交换文件(交换空间)之间切换。

在任何时刻,交换空间都限制着当前运行着的进程能够分配的虚拟页面的总数。

9.8.1 再看共享对象

一个对象可以被映像到虚拟存储器的一个区域,要么作为共享对象,要么作为私有对象.

私有对象的写时拷贝

9.8.2 再看fork函数

当fork函数被当前进程调用时:

1、内核为新进程创建内核数据结构,并分配给它唯一一个PID。

2、为了给新进程创建虚拟存储器[创建页目录]。

3、创建了当前进程的mm_struct,区域结构和页表的原样拷贝。

4、将两个进程的每个页面都标记为[只读]。并给两个区域进程的每个区域结构都标记为[私有的写时拷贝]。

注意:[没有对物理存储器进行拷贝,利用的是私有对象的写时拷贝技术。]

9.8.3 再看execve函数

假设运行在当前的进程中的程序执行了如下的调用:

execve("a.out",NULL,NULL);

execve函数在当前进程加载并执行目标文件a.out中的程序,用a.out代替当前程序。

加载并运行需要以下几个步骤。

1、删除已存在的用户区域:删除当前进程虚拟地址的用户部分中已存在的区域结构。

2、映射私有区域:为新程序的文本,数据,bss和栈区域创建新的区域结构。所有新的区域结构都是私有的,写时拷贝的。

文本和数据区域被映射到a.out文件中的文件和数据区。bss区域是请求二进制零,映射到匿名文件。

3、映射共享区域

4、设置程序计数器

5、execve最后一件事设置PC指向文本区域的入口点。

9.8.4 使用mmap函数的用户级存储器映射

Unix进程可以使用mmap函数来创建新的虚拟存储器区域,并将对象映射到这些区域中

#include

#include

void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset);

返回:若成功时则为指向映射区域的指正,若出错则为MAP_FAILED(-1).

munmap函数删除虚拟存储器的区域

#include

#include

void *munmap(void *start,size_t length);

返回:若成功则为0,若出错则为-1

练习题 9.5代码

#include

#include

#include

#include

#include "csapp.h" // 自己写的

#include

#include

int main(int argc, char* argv[]){

if (argc < 2)

csapp_error("lack of filename.");

int fd;

if ((fd = open(argv[1], O_RDWR)) < 0)

csapp_error2("open error",errno);

off_t length;

if ((length = lseek(fd, 0, SEEK_END)) < 0)

csapp_error2("lseek error.",errno);

char* bufptr = (char*)mmap(NULL,length,PROT_READ,MAP_PRIVATE,fd,0);

if (!bufptr)

csapp_error2("mmap error.", errno);

fprintf(stdout,"%s",bufptr);

exit(0);

}

mmap为什么比传统的读写速度要快

mmap : 将文件内容直接映射到进程的地址空间,通过对这段内存的读写,来达到对文件的读写目的;

read,write : 每次调用都需要从用户态到内核态的切换,且数据需要从用户态拷贝到内核态,然后再写入磁盘,增加了中间步骤

mmap的缺点 : 不能改变文件长度,无法写入多余的字符。

9.9 动态存储器分配

malloc通过调用sbrk函数来实现内存的分配,且在在sbrk之上加了一层对所分配的内存的管理,

而sbrk以及brk是实现从虚拟内存到内存的映射的

Linux内存分配小结--malloc、brk、mmap

动态存储器分配器维护着一个进程的虚拟存储区域,称为堆(heap)。

系统之间细节不同,但是不失通用型。

1、堆是一个请求二进制零的区域。

2、紧接着未初始化的bss区域,并向上生长(向更高的地址)。

3、对于每个进程,内核维护一个变量[brk],指向堆顶,当堆空间不足时,利用sbrk函数修改该变量。

4、分配器将堆视为一组不同大小的块block的集合来维护。

每个块就是一个连续的虚拟存储器片,要么是已分配,要么是空闲。

9.11 C程序中常见的与存储器有关的错误

linux动态分配全局置换,深入理解计算机系统 第九章 虚拟存储器相关推荐

  1. 深入理解计算机系统--第九章虚拟存储器

    9.虚拟存储器 为了更加有效地管理存储器且少出错,现代系统提供了对主存的抽象概念,叫做虚拟存储器(VM). 虚拟存储器是硬件异常,硬件地址翻译,主存,磁盘文件和内核软件的完美交互. 为每个进程提供一个 ...

  2. 深入理解计算机系统——第九章 Virtual Memory

    深入理解计算机系统--第九章 Virtual Memory 9.1 Physical and Virtual Addressing 9.2 Address Spaces 9.3 VM as a Too ...

  3. 读深入理解计算机系统 - 第一章 计算机系统漫游 - 1.1 信息 = 位 + 上下文

    1.1 信息 = 位 + 上下文 先说一下位,计算机的最小单位,一个位可以取两个值1/0(高电平/低电平)代表两种状态(1个位=1bit). 但是世界事物千千万,无法用一个位来表示,怎么办呢? 某不知 ...

  4. 19、深入理解计算机系统笔记,虚拟存储器,基本原理(1)

    1.一个系统中的进程是与其他进程共享CPU和主存资源的. 2.虚拟存储器(Virtual Memory),是硬件异常,硬件地址翻译,主存,磁盘文件和内核软件的完善交互,它为每个进程提供一个大的,一致的 ...

  5. 深入理解MAGENTO – 第九章 – 数据集合瓦瑞恩

    本来,作为一个PHP程序员,如果你想攒一组变量的相关你有一个选择,古老的 阵列 . 尽管共享一个地址的名称与C存储器的阵列,一个PHP数组是一种通用的字典可变数组索引像数值对象结合行为的影响. 在其他 ...

  6. 《深入理解计算机系统》----总结

    第一章     计算机系统漫游 主要内容:主要是全面精炼的概括了本书的内容,也就是"计算机系统概述",包括: a)      解释计算机系统中"信息"的概念:就 ...

  7. 《数学之美》——第九章 个人笔记

    数学之美 最近在读<数学之美>这本书,做一下个人笔记.看的是PDF,看完后会买一本的哦!版权意识还是有的. ps:图片文字都是这本书中的内容,侵权立删.会有点自己的理解. 第九章    图 ...

  8. 深入理解计算机系统(CSAPP)含lab详解 完结

    文章目录 深入理解计算机操作系统-第一章 1.1 信息就是位 + 上下文 1.2 程序被其他程序翻译成不同的格式 1.3 了解编译系统如何工作是大有益处的 1.4 处理器读并解释储存在内存中的指令 1 ...

  9. 深入理解计算机系统——知识总结(二)

    第 7 章 7.1 编译器驱动程序 7.2 静态链接 7.3 目标文件 7.4 可重定位目标文件 7.5 符号和符号表 7.6 符号解析 7.7 重定位 7.8 可执行目标文件 7.9 加载可执行目标 ...

最新文章

  1. mapreduce 丢数据_大数据之MapReduce详解
  2. ViSP中识别AprilTag的C++实例代码解释
  3. toad dba suite for oracle 12.1,Toad for Oracle 12.1下载地址
  4. socket简单通信
  5. C语言中Static和Const关键字的的作用
  6. ssh免密登录方法不生效?Authentication refused: bad ownership or modes for directory
  7. Java加密解密快速入门上篇【包括MD5、BASE64、DES、RSA等算法】
  8. 芜湖计算机专业哪个学校最好,芜湖IT行业那么火,到底哪些人适合学IT呢?
  9. html 脚本 gdi,基于gdi的简单画图
  10. 浅析Hibernate映射(五)——集合映射
  11. vue修改数组元素方法
  12. 知识图谱从0到-1的笔记——6.知识推理
  13. HTML超链接怎么做
  14. window设置oracle sid,window下改oracle_sid
  15. SpringBoot_01_初窥门径
  16. sql求平均日活_SQL 统计日活、月活指标
  17. 让华为小米抱团 统一推送联盟究竟是何方神圣?
  18. 为什么我要选择使用Yarn来做Docker的调度引擎
  19. Linux常用bash命令
  20. 最新版SEO优化指南:今年网站优化方案就靠它了!(基础版)

热门文章

  1. 文献管理工具mendeley登录问题
  2. 大数据之数据库mysql优化实战(一)
  3. 解决Windows下Arm下Linux下Qt4程序的中文乱码问题
  4. 关于Windows Phone 7开发工具离线安装包
  5. Nebula3学习笔记(6): 网络系统
  6. 基础教程推荐:跟微软大咖学BI
  7. windows不能改密码
  8. 去除SAP中的一些特殊字符
  9. 职场警示录:栽在邮件上的N种死法
  10. OO实现ALV TABLE 十一:ALV的聚合,排序,过滤