浅谈操作系统之虚拟内存

news/2024/7/20 13:25:34 标签: 操作系统, 内存管理, 虚拟内存

首先我们来一个概念
虚拟内存虚拟内存是一种内存管理技术,它会使程序自己认为自己拥有一块很大且连续的内存,然而,这个程序在内存中不是连续的,并且有些还会在磁盘上,在需要时进行数据交换
难以实现的物理寻址
我们把内存可以看成一个一维数组,那么这个数组的下标就是内存的物理地址,CPU用内存的物理地址来定位他想获取的内存块(数组中的内容),我们把这种方式称为物理寻址
如下图:
这里写图片描述
我们都知道,我们写的程序经过编译器编译成机器级语言后会被保存到文件中,当我们要运行它的时候,操作系统会将其加载到内存中并交给CPU去处理,CPU只处理一条条的指令。设想一下,如果内存中有一个程序,CPU通过系统总线去和内存中的指令和数据进行交互时,采用物理寻址将非常自然、方便,但是如果是两个程序或者多个程序会出现怎样的情况?
这里写图片描述
我们会看到两个程序中都有一条指令 mov eax (100),注意,这里的100是相对于正在运行的进程而言(单核),如果直接使用物理地址,那么就得分析每一个进程中的每一条指令,看看哪一个指令是操作内存的,并且要知道该进程的基值地址,然后把该指令中的位置(偏移量)加上该进程的基地址,分析指令是非常麻烦的,不容易实现,所以,我们引入了虚拟寻址(逻辑地址),如下图:
这里写图片描述
我们从图中可以看到,在使用虚拟寻址时(用逻辑地址),CPU会生成一个虚拟地址(逻辑地址),用这个虚拟地址来访问主存时需要经过一个MMU(内存管理单元)来对这个虚拟地址进行翻译,把这个虚拟地址变为真正的物理地址,对于每一个进程而言,它在执行的时候基址寄存器中的值是不一样的,比如上面的程序1,它的基址寄存器中的值为0,而对于程序2 寄存器中的值1000,这样一来CPU就不用分析当前进程中的指令了,当CPU执行一个指令的时候,它就认为所有关于内存地址的地址都是虚拟地址,然后发给MMU,经过MMU后就会将其翻译成真实的地址,最后,内存通过系统总线把数据给CPU传了过去。这里注意一个问题:MMU怎么知道当前进程的基地址?这是因为操作系统知道每一个进程的基地址,MMU(内存管理单元)硬件会利用放在主存中的查询表来动态地翻译虚拟地址,该表的内容是由操作系统管理的,也就是说,在进程进行切换的时候,这个基值寄存器中的值是会发生改变的。
那虚拟地址到底长什么样?请看下图:
这里写图片描述
每一个进程都有一个虚拟地址空间,而且结构非常相似
这样看起来一切顺利,但事实并非如此,因为我们的电脑内存很是有限,有些应用程序它需要很大的内存来运行它,这样一来,有时内存就不够用了,那应该怎样解决呢?
我们想到了局部性原理(上帝的法则),局部性原理有两个:
① 时间局部性: 意思是说,我电脑中的程序某一条指令在使用完之后,在不久的将来有很大可能再次地使用它
② 空间局部性: 这个是说,我电脑中的某一块内存在使用时,在不久的将来会使用内存地址相近的一块内存区域
所以我们决定,我们把应用程序代码不全部加载到内存中去,只是加载一小部分
接下来我们了解几个新的概念:
虚拟页和物理页
虚拟存储器系统把虚拟存储器分割成大小固定的块,这一块一块的存储器中的内容我们称为虚拟页[虚拟页不是真实存在的,而是逻辑上的],同样的道理,我们把物理存储器分割成物理页(内存中)
拥有虚拟页地址和物理页地址信息的页表
页表就是一个存放页表条目(Page Table Entry,PTE)的数组,里面存放了若干个页表条目,那么什么是页表条目呢?页表条目其实就是描述虚拟页信息的一块内存[物理](也可以说成数据结构[逻辑])如下图
这里写图片描述
我们可以简单地认为页表条目是由一个有效位和一个n位地址字段组成,有效位表明了该虚拟页当前是否被缓存到内存中了
了解了页表,我们再来看看物理页、虚拟页和页表之间的一个关系,虚拟页是虚拟存储系统把一个程序的虚拟地址空间划分了若干个虚拟页,(注意,这个虚拟页不是真正存在的东西),虚拟页有三种情况,一种是未分配的,不占用内存空间,第二种是未缓存的,也就是以存储在磁盘上的形式存在,还有一种是缓存的,也就是以存储在内存中的形式存在,接下来我门来看一个图
这里写图片描述
从这个图中我们可以看到,页表条目其实就是一个虚拟页的描述,它描述了虚拟页是否被缓存在内存中(有效位),以及虚拟页的存储位置(未分配的为null,缓存了的指向内存中物理页的地址,未缓存的指向磁盘中虚拟页的位置)
下来我们看看这个逻辑地址是如何工作的
在页面命中时,CPU硬件执行的步骤为:
第一步:处理器生成一个虚拟地址(VA),并把它传送给MMU
第二步:MMU生成页表条目的地址(PTEA),请求内存中的页表,让它给自己返回一个页表条目(PTE)
第三步:MMU构造物理地址(PA),然后把这这个物理地址传给内存(这时候是真实的物理地址),请求物理内存中的数据
第四步:内存返回所请求的数据给处理器
过程如下图:
这里写图片描述
这里我们不讨论页面不命中的时候
我们来看一个总图,来总结一下今天所提到的知识,看看到底在整个计算机中虚拟存储技术是如何工作的
这里写图片描述
到这里,我们可以发现,虚拟内存技术的核心就是利用了局部性原理,把所要运行的进程中的数据不全部加载到内存中执行,而是加载一部分,当CPU在请求页表时,发现页表中的页表条目中的有效位为0但是被虚拟存储系统分配了的虚拟页时,就会把这个虚拟页从磁盘中调度到内存中(往往磁盘中的数据不常用,而在内存中的物理页的数据是频繁使用的数据),这样一来,我们就实现了多个进程同时加载到内存中并且还占用不是很多的内存的效果了

更多内容,可关注趣谈编程公众号
这里写图片描述
本文参考《深入理解计算系统》和刘老师的讲课


http://www.niftyadmin.cn/n/885942.html

相关文章

批处理系统和分时系统的区别

要弄清批处理系统和分时系统的区别,首先我们得了解何为批处理系统和分时系统? 一、批处理系统 从字面上理解,就是一批一批的处理任务的一种系统,严格的定义,就是指用户将一批作业提交给操作系统后就不再干预&#xff0…

Unicode 与 UTF-8的关系

要弄清Unicode与UTF-8的关系,我们还得从他们的来源说起,下来我们从刚开始的编码说起,直到UTF-8的出现,我们就会感觉到他们之间的关系 1、ASCII码 我们都知道,在计算机的世界里,信息的表示方式只有0和1,但…

linux grep命令详解

简介 grep (global search regular expression(RE)and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。 Unix的grep家族包括grep、egrep和fgrep。egrep和fgrep的命令…

Java中补码的那些事

内存、显示器、键盘都是非常要好的哥们,他们协同合作为人类服务,但是人类却对键盘和显示器情有独钟,根本不关心内存长什么样子 那我们程序员写的那些代码,在计算机的世界里到底是怎样的呢? 先来看一段代码 int i 1…

JVM之类文件结构——上篇(常量池)

Java语言之所以强大的一个原因就在于它具有跨平台性,Java源文件被编译后的结果不是本地机器码(与机器平台相关联)而是字节码(与机器平台无关),然后由JVM将字节码去加载并执行它。 那么Java的字节码文件到底长什么样? …

shell -- 日期格式化显示和日期的加减

1. 显示当前日期时间. $ date Mon Jun 2 13:55:47 HKT 2014 当前时间戳: date %s 2. 按照指定格式显示当前时间(date format). (1). 显示年月日. $ date "%Y-%m-%d" 2014-06-02 $ date "%F" 2014-06-02 $ date "%Y/%m/%d" 2014/06/02 补充…

操作系统之进程和线程

LZ水平有限,如果发现有错误之处,欢迎大家指出,或者觉得那块说的不好,欢迎建议。希望和大家一块讨论学习 LZ QQ:1310368322 进程和线程理解起来比较抽象,是因为它本来就是一种抽象,一种操作系统层面的抽象。…

shell -- 数学计算总结

shell中的赋值和操作默认都是字符串处理,在此记下shell中进行数学运算的几个特殊方法,以后用到的时候可以来看,呵呵。 1、错误方法举例 a) var11 echo$var 输出的结果是11,悲剧,呵呵 b) var1 var$var1 echo$var 输出结…