虚拟存储器(1)——虚存概念及页、页表和地址翻译基础 虚拟存储器[转载]

转载于http://blog.csdn.net/u013471946/article/details/46890933 加了一些自己的理解

一、前言

虚拟存储器,感觉很难,至少说很复杂,里面涉及到的东西也比较枯燥。当然,如果能彻底搞清楚,对继续学习操作系统原理是百利无一害的。

玩C或C++的人,经常通过&a的方式获取变量地址,并将其赋值给指针变量,也通常用printf打印出地址的值,类似0x8048

034之类的地址值,但要从此刻开始要明确一点,你打印出的这个地址值,根本不是内存里的真实值,而是通过链接器最终生成的虚拟地址,这个虚拟地址帮助程序在操作系统进程中正常运行,而每个进程里的虚拟存储分布的值几乎都一样……所以才会出现,你各进程中打印出的地址为啥分布区间那么相似。

虚拟存储器是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每个进程提供了一个大的、一致的、私有的地址空间。它有三个重要的功能:

①它将物理内存看成磁盘的高速缓存,永远只保留活动区域,从而高效利用物理内存

②它为每个进程提供一致的线性地址空间,从而简化存储器管理

③它保护每个进程的地址空间不被其他进程破坏。

真实物理内存中,空闲空间并非连续,可能零散的分布在各个角落,而虚拟存储器,就是把各对象的地址值分布在连续线性的逻辑地址空间中。那么如何将线性地址和零散的物理地址对应起来呢?这就需要地址翻译。CPU在处理对象地址时,利用内部MMU,通过访问存放在物理内存中的查询表来动态翻译虚拟地址,该表内容是由操作系统管理的。

扯了这么多是不是觉得很乱? 这里涉及到一个重要的存储器层次结构的概念。回忆下我写的《程序性能优化探讨(3)》章中的第一节就讲到“存储器层次结构”。里面图清晰的把存储器层次结构描述了出来:存储速度由快到慢、由高到低一次是:CPU寄存器、L1\L2\L3高速缓存(SRAM)、主存(内存,DRAM)、磁盘……

当世界上还有没有虚拟存储器概念时,内存DRAM显然就是磁盘的上一级缓存,就像SRAM是内存DRAM的上一级缓存一样类似。but现在发展出了虚拟存储器的概念,在磁盘上开辟了连续的空间玩票,那么我们可以理解为:虚拟存储器VM事实上成为磁盘的缓存!而谁又是VM的上一级缓存呢?自然而然就应该想到是内存DRAM。事实上VM相当于从存储器体系中的内存和磁盘之间的位置强行插入,新增的一个层次罢了!为啥要强插?很简单。因为磁盘读取速度实在太慢,极端情况下可能比DRAM的速度慢10 0000倍,根据存储器层次结构的思想,为了调和速度差,增加一个叫做虚拟存储器的缓存结构也就理所当然了。

二、虚拟存储器一般性概念

虚拟存储器成简称为VM。

先来看下比较拗口概念解释:虚拟存储器被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组……这句话除了觉得很抽象外,我们至少能获得两个关键信息:

①虚拟存储器的载体是磁盘,他和其他存储器一样,存放数据,而且它在磁盘上是连续存储的;

②虚拟存储器的每个字节数据一定对应唯一的1bit虚拟地址。

首先,我们要分清楚虚拟存储器和虚拟地址的区别,一个是逻辑上存储数据的对象;一个是逻辑上标识这些数据的概念地址。根据以上的定义,我们可以YY一下虚拟存储器的大概应用:虚拟存储器似乎和物理存储器有某种强对应关系,它利用磁盘上连续的存储数据,可以实现线性连续地址空间访问。也许他能优化磁盘与物理内存器之间的通信关系。

接下来我们先恶补看下什么是线性地址空间。回忆下,比如你有n位(bit)的,数据位,你能表达最大的整数就是2^(n) - 1,你能表示的所有整数的个数就是N=2^(n),(注意哦,最大整数是从0起的,而数个数是从1起:)),也就是说,能表示的所有数为:(0,1,2,…,N-1)这N个数。如果每个数都来标识一个地址,而每个地址又代表8字节(byte)的大小的空间,那么N个整数就能标识N*8字节的线性地址空间。

举个例子,32位机,由于是32bit,而每个字节又是8bit,所以32位机就是由4byte组成地址值。比如0x12345678,就是典型的4字节,32位。注意这里的位(bit)可不是16进制0x里表示的某一个位哦!而是比如0x12,表示一个字节,对应8位,它的二进制就是00010010。

32位系统的n=32,那么N=2^(2+10+10+10)=4Gbit,它的线性地址空间就是(0,1,2,...,4G-1)。这里再废话一下,为啥说32位机可以标识最大4Gbyte的地址,而这里算出来最大是4Gbit?哼哼!傻瓜才去用1bit地址对应1bit数据,那样多浪费啊!肯定是1bit地址对应8bit的数据,也就是说一位地址对应一字节数据,这样才合理嘛!!!

我们设n和N表示虚拟地址空间,m和M表示实际物理地址空间。有了前面的铺垫,我们可以想象一下,一字节数据,比一定只对应1bit地址哦!可以有多个1bit地址号称标识这一字节数据哦!至少目前,我们有N和M两个地址空间,可以同时来标识某一字节的数据!

接下来描述一个事实:磁盘上的数据要想缓存到物理内存中,不可能一位一位缓存进内存,也不可能一字节一字节缓存进内存。那到底以多大的批量缓存呢?我们把这个批量称为块,磁盘上的数据被分割为块,将它作为磁盘与内存之间的传输单元。好了,虚拟内存如果要来凑热闹,也得有相应的机制,于是VM系统也将VM分割成固定大小的块,我们将它称为虚拟页(VP)。这虚拟页既然有某个固定大小,肯定是多少字节之类的单位,于是我们定义虚拟页大小为P=2^p字节。当然,物理内存肯定也有类似的页大小。

卡住!是不是又有点晕了?P=2^p字节是个什么东东?这里我们可以借助极限思维来想象一下:如果压根没有虚拟页这种东西,那么我们传数据通常一字节一字节来玩,于是此时p=0,P=1字节,对否?哦,也就是说,这里的p,很类似N=2^n,利用位的概念来标识虚拟页的字节大小。假设VM系统的源代码里要定义虚拟页大小,应该是类似unsigned char page_addr_len之类的变量,就可以标识虚拟页P大小是256 = 2^8。

开始的确有点难理解,其页实也就是定义页的大小,但为什么是以2为低其实也很好理解,你的内存大小不也是以2为底来计算多少个字节。

好了,我们知道由于虚拟页的存在,将连续的虚拟存储空间分割成若干个虚拟页,当虚拟页大小是P字节,而我们又晓得整个虚拟空间大小是N字节,于是能轻易得出,虚拟存储器被分割成N/P=2^(n-p)个页,也就是我们得到虚拟页空间(0,1,2,……,N/P-1)。

同理,物理内存也有类似的分页概念,也被分割成M/P=2^(m-p)个页,于是得出物理页空间(0,1,2,……,M/P-1)。

三、虚拟页和页表

好了,有了这么冗长的铺垫,再来看下面的图,应该没那么懵了吧:

左边的VP代表虚拟页面,右边的PP代表物理页面,我们可以看到,虚拟存储器中的页原封不动的对应上了物理存储器中的页。

虚拟页面的集合都分为三个不相交的子集:

未分配的:说明该页没对应任何数据,因此就不占用磁盘空间……哇塞,大家有没有发现——不占用磁盘空间!难道说,VM虽然在磁盘上申请了连续空间,但它具体使用时不一定按连续的方式占用空间?有待考证;

缓存的:当前缓存在物理存储器中的已分配页……首先它得是已分配的页(有数据和它关联),并且当前正临时放在物理存储器中玩的页;

未缓存的:没有缓存在物理存储器中已分配的页……首先它也是已分配的页(有数据和它关联),只是暂时被剔除出物理存储器了。

神马?有人问为啥图的右边比左边短?→_→介个……我想说的是,两边在某个极端情况下可能一样高,此时M=N,这是什么时候?当你玩32位机时,土豪般的插了4G的内存条, 有可能两边一样长O(∩_∩)O~一般来说,屌丝插的内存条肯定少于理论最大内存值的,而虚拟存储器是可以设置成理论最大值,不信你到windows设置中找到虚拟内存设置,我的32机允许设置的最大值就是4092MB,因此作者画这个图时也充分考虑了这种普遍性……作者真为屌丝考虑O(∩_∩)O~

既然DRAM缓存的虚拟页面,那VM系统总需要一个种方法来判定某个虚拟页是否存放在DRAM中,如果是,系统还必须确定这个虚拟页存放在(DRAM)中哪个物理页中;如果不是(不命中),VM系统还必须寻找这个虚拟页在磁盘的什么位置。这就有两种情况:

①该虚拟页已经被VM系统分配,只是该虚拟页还未被缓存到DRAM中——说明该虚拟页已经对应上了磁盘里具体的某块数据

②该虚拟页还未被VM系统分配,也就是说这个虚拟页编号在VM看来还不存在——说明在磁盘上的虚拟存储器中找不到该虚拟页号(这种强行访问可能会出段错误哦!!!)

问题就是,谁来标识虚拟页这些不同的状态呢?答案是页表!首先注意,页表是专门存放在内存DRAM中特定区域的,它全面记录了所有可能的虚拟页号的当前情况:

从上图中可以看出,右上方的表,描述了内存DRAM中PP0~PP3Z这4个物理页中存放的VP1~VP4这四个虚拟页表;右下方的表,描述了虚拟存储器中已分配的虚拟页号;

而左边的表,就是大名鼎鼎的页表。PTE是页表条目,有效位为1时说明该虚拟页缓存在DRAM中,否则便有是上面描述过的两种情况:

①VP3和VP6两个虚拟页已经被分配,只是暂未缓存到DRAM中;

②VP0和VP5两个虚拟页还未被分配,于是对应的PTE0和PTE5就是null——说明这两个页号还没映射磁盘上的其他数据(比如暂时没需求),因此页表自然也将其置空了。

好了,这么完美动人的页表,是谁来生成和维护呢?答案是操作系统,而且操作系统还要负责完成磁盘和DRAM之间具体的传送页工作。

那又是谁会需要去读取页表的内容呢?是CPU里MMU(存储器管理单元)中的地址翻译硬件,当CPU需要将一个虚拟地址转换成物理地址时,都会读取页表的内容。

说到这我们稍微总结一下:虚拟存储器部署在磁盘上;页表部署在内存中;OS维护页表内容;MMU读取页表内容。

一旦理解了页表,类似页命中和缺页就好理解了。比如上图中你引用VP1\2\7\4都是页命中,可你要想起引用下VP3,地址翻译硬件读取PTE3时发现有效位0,于是处罚缺页异常。

缺页也没什么大不了,此时内核会调用异常处理程序,通过某种策略决定要赶走PP3中的VP4,此时无论VP4是否被修改,内核都会将其写回磁盘,然后从磁盘拷贝VP3到存储器PP3中,并更新PTE3,随后返回并重启导致缺页的指令,地址翻译硬件会重新翻译VP3的虚拟地址到物理地址,如下图:

这里专门提一下,以上讨论都针对的虚拟存储器——页表——物理存储器之间的数据交换,那么虚拟存储器和磁盘上原始数据的关系如何呢?是否清楚?事实上,每个进程都有自己的虚拟存储器,相当于每个进程都在磁盘上开辟了属于自己的虚拟页空间,因此每个进程都有诸如VP1~VP7这些虚拟页存储在磁盘上,因此物理存储器中也为每个进程准备了独立的页表。但是,物理存储器却可能被不同进程的虚拟页共享到同一个物理页上!这有什么好处呢,比如标准库中的printf函数,每个进程都可以将这个相应的虚拟页映射到同一个物理页上。

还有一个更神奇的细节,既然磁盘上的可执行文件在变成进程时,又会在磁盘上的虚拟存储器中开辟属于自己的私有虚拟页区域,那么可执行文件的文本部分(.init、.text、rodata等)就会同时出现在磁盘的两个位置?!也就是说,我们所谓的linux进程的存储器映射(如下图),根本就不放在内存中,而是放在磁盘中?!是不是很毁三观?事实上,加载器从来不把任何可执行文件的数据拷贝到物理存储器中,而是在页面第一次被引用时,由虚拟存储器系统从磁盘调入物理存储器的!也就是说,下图这个伟大的进程映射的实体,事实上是放在磁盘中的虚拟存储器里,并且被VM系统分配成诸如VP1~VP7这些虚拟页面,然后按需依次调入物理存储器的!

四、地址翻译

 

地址翻译听起来很高大上,但如果看明白上面的讲解,尤其是理解了虚拟页物理页以及页表的概念,那理解起地址翻译来也是灰常容易的!

回忆下,既然虚拟存储器被分配成一个个虚拟页,每个虚拟页大小的是2^p字节,那肯定有一个方法去识别,某个字节或者某段数据具体属于哪个虚拟页,又在这个页的哪个位置,对否?既然虚拟页大小是2^p字节,说明我们用p位二进制地址就能标识这个页中的每一个字节了。而虚拟地址共n位,也就说还剩n-p位,干嘛呢?当然是标识虚拟页号了,有n-p位就能标识2^(n-p)个虚拟页。(注意哦,2^p的单位是字节,2^(n-p)的单位是“个”千万别搞混!)

我们把标识2^p字节虚拟页中具体字节位置的量称为虚拟页面偏移量,用VPO表示;把标识2^(n-p)个虚拟页的号称为虚拟页号,用VPN表示。于是就有下面的虚拟地址结构:

VPN     (n-p)位 VPO    p位

而物理页也有相同的结构,其物理地址结构:

PPN     (n-p)位 PPO    p位

再回忆下,页表这个东西,为什么能把虚拟页和物理页对应联系起来呢?事实上,页表条目的PTE数组才是对应关系的关键,PTE数组下标能对应相应的虚拟页号VPN,而数组中存的又是物理页号PPN,这样当VPN与PPN建立强联系后,剩下的偏移位,直接将VPO复制给PPO就完事,于是有了下面的过程图:

这里又会涉及到一个现象,既然物理内存有上一级缓存SRAM,比如说就是L1,CPU中MMU与物理内存之间的任何数据交换都会经过L1的查找和处理。比如,MMU需要和物理内存交换PTE、PTEA(PTE的标号)、PA(物理地址)这些信息,L1都会检查是否先前已有缓存。如果命中,直接由L1提供MMU所需的数据;如果不命中,则由L1向物理内存申请数据,于是就有了下图的过程:

那么MMU在访问L1时,是用物理地址还是虚拟地址呢?相信自己脑补都应该有结论,肯定是物理地址啦!至少大部分系统都是这么处理的。

五、利用TLB加速地址翻译

从目前的设计来看,MMU如果需要翻译CPU产生的虚拟地址,就必须获得PTE,恰巧L1命中的情况还好,若不命中,就得花费几十上百的周期到物理内存中调用。而贪婪的人类试图尽可能的消除这样的开销,于是在MMU中专门开辟了一个小的缓冲区,称为翻译后备缓冲器TLB(Translation Lookaside Buffer)。

事实上,TLB很类似对虚拟地址已有的划分策略,比如之前我们把虚拟地址划分为VPN和VPO,都是为了体现特定的层次结构。那么现在可以把VPN部分再进行划分:

TLB是由标记(TLBT)和索引(TLBI)组成,如果TLB有T=2^t个组,那么TLBI就刚好是t位,而VPN剩余位就刚好留给TLBT……留来干什么?其实我也还搞不清楚,待下节分解。

时间: 2024-10-14 08:46:56

虚拟存储器(1)——虚存概念及页、页表和地址翻译基础 虚拟存储器[转载]的相关文章

操作系统内存管理之 分页与虚存(页表、页框、内存)

一 页面与页表 1 页面 分页存储管理是将作业的逻辑地址划分为一系列同等大小的部分,称为页.并为各页加以编号,每个作业的页的编号都是从0开始的.与之类似,把可用的物理内存也划分为同样大小的连续的部分,称为块或页框.同样为块也进行标号,从0#开始.在为进程分配内存空间时,以页为单位,每个内存中的块存放一页用户作业.只要内存中有足够多的块,这些块可以相邻也可以不相邻,就可以存放整个作业了. 页面的大小对于内存利用和系统开销来说非常重要,页面太大,在作业的最后一页必然会剩余较大不能利用的空间--内碎片

虚拟存储器(2)——端到端地址翻译与多级页表

一.端到端地址翻译示例 上节我们刚把TLB开了个头,多说无益,还是具体来玩个实际例子吧,具体来做一个端到端(虚拟地址到物理地址)的地址翻译示例,来统筹下之前讲的知识点.先来做如下约定: 1.老规矩,存储器按字节寻址,访问也按一字节访问: 2.虚拟地址14位长(n=14),物理地址12位长(m=12),位数上点玩起来方便: 3.页面大小是64字节(P=64),也就是说(p=6) 4.TLB是四路组相联,总共16个条目: 5.L1 d-cache是物理寻址.直接映射的,行大小为4字节,总共有16个组

软考总结——虚存管理

?? 存储管理是操作系统的重要职能之中的一个,主要任务是对内存空间进行分配与回收. 因为计算机内存容量有限(如今一般都是32位或64位系统),而外存储设备的容量增长速度很快,比如移动硬盘已经到了T的级别,这时假设要訪问这块儿移动硬盘内的大数据,我们的计算机就有点力不从心了. ..故在此基础上发展了虚拟存储系统. 虚存理念:利用有限资源尽可能的运行大程序.对用户程序和内存进行分块,将用户程序一块块拿到内存中来,一个运行完后释放内存,下一个继续运行. 虚拟存储通过将执行进程訪问的地址(逻辑地址.虚拟

虚存管理页面置换算法 — FIFO和RUL算法模拟实现

本篇博文为追忆曾经写过的算法系列第一篇(20081021) 温故知新 目的: 为了解决内存容量有限与多作业运行的冲突,运用了虚拟存储技术,能从逻辑上对内存进行扩充,达到扩充内存的效果.分页存储管理是实现虚拟存储的一种方案.通过模拟算法的实验,加深理解,虚拟存储器的基本原理和方法. 要求: 1.请求分页的置换算法(FIFO && RUL算法实现):2.按给定的顺序列,输出页面调度过程包括命中 / 缺页,调入/调出:3.计算缺页率,频率. 说明: vp_list[N] //访问序列 bs[M]

地址映象和变换(一)之主存虚存

地址映象:是将每一个虚存单元按某种规则装入实存,即建立多用户虚地址与实存地址之间的相应关系. 地址变换:是程序依照这样的映象关系装入实存后.在运行时,多用户虚地址怎样变换成相应的实存地址. 页面争用(实页冲突):发生两个以上的虚页想要进入主存中同一个页面位置的现象. 因为虚存空间远远大于实存空间,因此页式虚拟存储器常採用全相联映像. 替换算法 当发生页面失效时.要从磁盘中调入一页到主存. 假设主存全部页面都已经被占用,必须从主存储器中淘汰掉一个不常使用的页面.以便腾出主存空间来存放新调入的页面.

57-4 数据库分片概念及mongodb sharding的实现

04 数据库分片的概念及mongodb sharding的实现 配置环境: node1: 192.168.1.121 CentOS release 6.7 node2: 192.168.1.122 CentOS release 6.7 node3: 192.168.1.123 CentOS release 6.7 [[email protected] ~]# vim /etc/hosts 添加 192.168.1.121   node1 192.168.1.122   node2 192.168

第五十一课 NoSQL基础概念及MongoDB应用、数据库分配概念

NoSQL基础概念及MongoDB MongoDB基础应用 MongoDB索引及复制集 数据库分片的概念及Mongodb  sharding的实现 一.NoSQL基础概念 NoSQL(Not Only SQL),是一种技术流派,非关系型数据库:适合用在大数据领域,各种nosql有各自的查询语句,这也是nosql的缺点之一. 大数据(BigDate)也称海量数据是一个模糊的概念,像Google.百度收集大量数据,分析现在.预测未来:这些数据通过某些特定的特征和算法得出某些预测的结果,这些数据为大数

正则表达式基本概念及在java中的使用

正则表达式,我是从why,what,how开始探索的... why:正则表达式用“俗语”解释是什么意思?“历史”上发生了什么事情,让正则表达式诞生了? what:正则表达式具体内容是什么?包含什么定义?这些定义分别用来做什么? how:我在用java,那么正则表达式和java又是怎么联系起来的呢? 伴随着这些问题的解决,对正则表达式有了初步的理解,习惯性用脑图将这些内容整理,希望和大家一起沟通,互相进步~ 正则表达式基本概念及在java中的使用,布布扣,bubuko.com

数据库基本概念及Oracle基本语句

一.数据库分类 通常是按照数据模型的特点将传统数据库系统分成网状数据库.层次数据库和关系数据库三种. 1.网状数据库 顾名思义,网状数据库采用的是以记录类型为结点的网状数据模型,是一种导航式(Navigation)的数据库--用户在操作数据库时不但要指明要访问的对象(数据),还要规定其存取路径. 网状数据库模型对于层次和非层次结构的信息都能比较自然的模拟,在关系数据库出现之前网状DBMS要比层次DBMS用得普遍.在数据库发展史上,网状数据库占有重要地位. 2.层次型数据库 紧随网络型数据库之后出