彻底理解内存概念

基本知识
  ●内存
  内存就是存储程序以及数据的地方,比如当我们在使用WPS处理文稿时,当你在键盘上敲入字符时,它就被存入内存中,当你选择存盘时,内存中的数据才会被存入硬(磁)盘。在进一步理解它之前,还应认识一下它的物理概念。
  ●只读存储器(ROM)
  ROM表示只读存储器(Read Only Memory),在制造ROM的时候,信息(数据或程序)就被存入并永久保存。这些信息只能读出,一般不能写入,即使机器掉电,这些数据也不会丢失。ROM一般用于存放计算机的基本程序和数据,如BIOS ROM。其物理外形一般是双列直插式(DIP)的集成块。
  ●随机存储器(RAM)
  随机存储器(Random Access Memory)表示既可以从中读取数据,也可以写入数据。当机器电源关闭时,存于其中的数据就会丢失。我们通常购买或升级的内存条就是用作电脑的内存,内存条(SIMM)就是将RAM集成块集中在一起的一小块电路板,它插在计算机中的内存插槽上,以减少RAM集成块占用的空间。目前市场上常见的内存条有4M/条、8M/条、16M/条等。
  ●高速缓冲存储器(Cache)
  Cache也是我们经常遇到的概念,它位于CPU与内存之间,是一个读写速度比内存更快的存储器。当CPU向内存中写入或读出数据时,这个数据也被存储进高速缓冲存储器中。当CPU再次需要这些数据时,CPU就从高速缓冲存储器读取数据,而不是访问较慢的内存,当然,如需要的数据在Cache中没有,CPU会再去读取内存中的数据。
  当你理解了上述概念后,也许你会问,内存就是内存,为什么又会出现各种内存名词,这到底又是怎么回事呢?
  在回答这个问题之前,我们再来看看下面这一段。

  物理存储器和地址空间
  物理存储器和存储地址空间是两个不同的概念。但是由于这两者有十分密切的关系,而且两者都用B、KB、MB、GB来度量其容量大小,因此容易产生认识上的混淆。初学者弄清这两个不同的概念,有助于进一步认识内存储器和用好内存储器。
  物理存储器是指实际存在的具体存储器芯片。如主板上装插的内存条和装载有系统的BIOS的ROM芯片,显示卡上的显示RAM芯片和装载显示BIOS的ROM芯片,以及各种适配卡上的RAM芯片和ROM芯片都是物理存储器。
  存储地址空间是指对存储器编码(编码地址)的范围。所谓编码就是对每一个物理存储单元(一个字节)分配一个号码,通常叫作“编址”。分配一个号码给一个存储单元的目的是为了便于找到它,完成数据的读写,这就是所谓的“寻址”(所以,有人也把地址空间称为寻址空间)。
  地址空间的大小和物理存储器的大小并不一定相等。举个例子来说明这个问题:某层楼共有17个房间,其编号为801~817。这17个房间是物理的,而其地址空间采用了三位编码,其范围是800~899共100个地址,可见地址空间是大于实际房间数量的。
  对于386以上档次的微机,其地址总线为32位,因此地址空间可达232即4GB。但实际上我们所配置的物理存储器通常只有1MB、2MB、4MB、8MB、16MB、32MB等,远小于地址空间所允许的范围。从下图中我们可以看到地址空间与物理存储器之间的关系。

  

  好了,现在可以解释为什么会产生诸如:常规内存、保留内存、上位内存、高端内存、扩充内存和扩展内存等不同内存类型。

  各种内存概念
  这里需要明确的是,我们讨论的不同内存的概念是建立在寻址空间上的。
  IBM推出的第一台PC机采用的CPU是8088芯片,它只有20根地址线,也就是说,它的地址空间是1MB。
  PC机的设计师将1MB中的低端640KB用作RAM,供DOS及应用程序使用,高端的384KB则保留给ROM、视频适配卡等系统使用。从此,这个界限便被确定了下来并且沿用至今。低端的640KB就被称为常规内存即PC机的基本RAM区,请看图1。保留内存中的低128KB是显示缓冲区,高64KB是系统BIOS(基本输入/输出系统)空间,其余192KB空间留用。从对应的物理存储器来看,基本内存区只使用了512KB芯片,占用0000至80000这512KB地址。显示内存区虽有128KB空间,但对单色显示器(MDA卡)只需4KB就足够了,因此只安装4KB的物理存储器芯片,占用了B0000至B10000这4KB的空间,如果使用彩色显示器(CGA卡)需要安装16KB的物理存储器,占用B8000至BC000这16KB的空间,可见实际使用的地址范围都小于允许使用的地址空间。
  在当时(1980年末至1981年初)这么“大”容量的内存对PC机使用者来说似乎已经足够了,但是随着程序的不断增大,图象和声音的不断丰富,以及能访问更大内存空间的新型CPU相继出现,最初的PC机和MS-DOS设计的局限性变得越来越明显。
  1.什么是扩充内存?
  EMS工作原理
  到1984年,即286被普遍接受不久,人们越来越认识到640KB的限制已成为大型程序的障碍,这时,Intel和Lotus,这两家硬、软件的杰出代表,联手制定了一个由硬件和软件相结合的方案,此方法使所有PC机存取640KB以上RAM成为可能。而Microsoft刚推出Windows不久,对内存空间的要求也很高,因此它也及时加入了该行列。
  在1985年初,Lotus、Intel和Microsoft三家共同定义了LIM-EMS,即扩充内存规范,通常称EMS为扩充内存。当时,EMS需要一个安装在I/O槽口的内存扩充卡和一个称为EMS的扩充内存管理程序方可使用。但是I/O插槽的地址线只有24位(ISA总线),这对于386以上档次的32位机是不能适应的。所以,现在已很少使用内存扩充卡。现在微机中的扩充内存通常是用软件如DOS中的EMM386把扩展内存模拟或扩充内存来使用。所以,扩充内存和扩展内存的区别并不在于其物理存储器的位置,而在于使用什么方法来读写它。下面将作进一步介绍。
  前面已经说过扩充存储器也可以由扩展存储器模拟转换而成。EMS的原理和XMS不同,它采用了页帧方式。页帧是在1MB空间中指定一块64KB空间(通常在保留内存区内,但其物理存储器来自扩展存储器),分为4页,每页16KB。EMS存储器也按16KB分页,每次可交换4页内容,以此方式可访问全部EMS存储器。图2给出了EMS的工作原理。符合EMS的驱动程序很多,常用的有EMM386.EXE、QEMM、TurboEMS、386MAX等。DOS和Windows中都提供了EMM386.EXE。
  2.什么是扩展内存?
  我们知道,286有24位地址线,它可寻址16MB的地址空间,而386有32位地址线,它可寻址高达4GB的地址空间,为了区别起见,我们把1MB以上的地址空间称为扩展内存XMS(eXtend memory)。
  在386以上档次的微机中,有两种存储器工作方式,一种称为实地址方式或实方式,另一种称为保护方式。在实方式下,物理地址仍使用20位,所以最大寻址空间为1MB,以便与8086兼容。保护方式采用32位物理地址,寻址范围可达4GB。DOS系统在实方式下工作,它管理的内存空间仍为1MB,因此它不能直接使用扩展存储器。为此,Lotus、Intel、AST及Microsoft公司建立了MS-DOS下扩展内存的使用标准,即扩展内存规范XMS。我们常在Config.sys文件中看到的Himem.sys就是管理扩展内存的驱动程序。
  扩展内存管理规范的出现迟于扩充内存管理规范。
  3.什么是高端内存区?
  在实方式下,内存单元的地址可记为:
       段地址:段内偏移
  通常用十六进制写为XXXX:XXXX。实际的物理地址由段地址左移4位再和段内偏移相加而成。若地址各位均为1时,即为FFFF:FFFF。其实际物理地址为:FFF0+FFFF=10FFEF,约为1088KB(少16字节),这已超过1MB范围进入扩展内存了。这个进入扩展内存的区域约为64KB,是1MB以上空间的第一个64KB。我们把它称为高端内存区HMA(High Memory Area)。HMA的物理存储器是由扩展存储器取得的。因此要使用HMA,必须要有物理的扩展存储器存在。此外HMA的建立和使用还需要XMS驱动程序HIMEM.SYS的支持,因此只有装入了HIMEM.SYS之后才能使用HMA。
  4.什么是上位内存?
  为了解释上位内存的概念,我们还得回过头看看保留内存区。保留内存区是指640KB~1024KB(共384KB)区域。这部分区域在PC诞生之初就明确是保留给系统使用的,用户程序无法插足。但这部分空间并没有充分使用,因此大家都想对剩余的部分打主意,分一块地址空间(注意:是地址空间,而不是物理存储器)来使用。于是就得到了又一块内存区域UMB。
  UMB(Upper Memory Blocks)称为上位内存或上位内存块。它是由挤占保留内存中剩余未用的空间而产生的,它的物理存储器仍然取自物理的扩展存储器,它的管理驱动程序是EMS驱动程序。
  5.什么是SHADOW(影子)内存?
  对于细心的读者,可能还会发现一个问题:即是对于装有1MB或1MB以上物理存储器的机器,其640KB~1024KB这部分物理存储器如何使用的问题。由于这部分地址空间已分配为系统使用,所以不能再重复使用。为了利用这部分物理存储器,在某些386系统中,提供了一个重定位功能,即把这部分物理存储器的地址重定位为1024KB~1408KB。这样,这部分物理存储器就变成了扩展存储器,当然可以使用了。但这种重定位功能在当今高档机器中不再使用,而把这部分物理存储器保留作为Shadow存储器。Shadow存储器可以占据的地址空间与对应的ROM是相同的。Shadow由RAM组成,其速度大大高于ROM。当把ROM中的内容(各种BIOS程序)装入相同地址的Shadow RAM中,就可以从RAM中访问BIOS,而不必再访问ROM。这样将大大提高系统性能。因此在设置CMOS参数时,应将相应的Shadow区设为允许使用(Enabled)。

  总 结
  经过上面分析,内存储器的划分可归纳如下:
  ●基本内存 占据0~640KB地址空间。
  ●保留内存 占据640KB~1024KB地址空间。分配给显示缓冲存储器、各适配卡上的ROM和系统ROM BIOS,剩余空间可作上位内存UMB。UMB的物理存储器取自物理扩展存储器。此范围的物理RAM可作为Shadow RAM使用。
  ●上位内存(UMB) 利用保留内存中未分配使用的地址空间建立,其物理存储器由物理扩展存储器取得。UMB由EMS管理,其大小可由EMS驱动程序设定。
  ●高端内存(HMA) 扩展内存中的第一个64KB区域(1024KB~1088KB)。由HIMEM.SYS建立和管理。
  ●XMS内存 符合XMS规范管理的扩展内存区。其驱动程序为HIMEM.SYS。
  ●EMS内存 符合EMS规范管理的扩充内存区。其驱动程序为EMM386.EXE等。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhongrg/archive/2007/11/12/1879980.aspx

 

在硬件工程师和普通用户看来,内存就是插在或固化在主板上的内存条,它们有一定的容量——比如64 MB。但在应用程序员眼中,并不过度关心插在主板上的内存容量,而是他们可以使用的内存空间——他们可以开发一个需要占用1 GB内存的程序,并让其在OS平台上运行,哪怕这台运行主机上只有128 MB的物理内存条。而对于OS开发者而言,则是介于二者之间,他们既需要知道物理内存的细节,也需要提供一套机制,为应用程序员提供另一个内存空间,这个内存空间的大小可以和实际的物理内存大小之间没有任何关系。
  
  我们将主板上的物理内存条所提供的内存空间定义为物理内存空间;将应用程序员看到的内存空间定义为线性空间。物理内存空间大小在不同的主机上可以是不一样的,随着主板上所插的物理内存条的容量不同而不同;但为应用程序员提供的线性空间却是固定的,不会随物理内存的变化而变化,这样才能保证应用程序的可移植性。尽管物理内存的大小可以影响应用程序运行的性能,并且很多情况下对物理内存的大小有一个最低要求,但这些因素只是为了让一个OS可以正常的运行。
  
  线性空间的大小在32-bit平台上为4 GB的固定大小,对于每个进程都是这样(一个应用可以是多进程的,在OS眼中,是以进程为单位的)。也就是说线性空间不是进程共享的,而是进程隔离的,每个进程都有相同大小的4 GB线性空间。一个进程对于某一个内存地址的访问,与其它进程对于同一内存地址的访问绝不冲突。比如,一个进程读取线性空间地址1234ABCDh可以读出整数8,而另外一个进程读取线性空间地址1234ABCDh可以读出整数20,这取决于进程自身的逻辑。
  
  在任意一个时刻,在一个CPU上只有一个进程在运行。所以对于此CPU来讲,在这一时刻,整个系统只存在一个线性空间,这个线性空间是面向此进程的。当进程发生切换的时候,线性空间也随着切换。所以结论就是每个进程都有自己的线性空间,只有此进程运行的时候,其线性空间才被运行它的CPU所知。在其它时刻,其线性空间对于CPU来说,是不可知的。所以尽管每个进程都可以有4 GB的线性空间,但在CPU眼中,只有一个线性空间的存在。线性空间的变化,随着进程切换而变化。
  
  尽管线性空间的大小和物理内存的大小之间没有任何关系,但使用线性空间的应用程序最终还是要运行在物理内存中。应用所给出的任何线性地址最终必须被转化为物理地址,才能够真正的访问物理内存。所以,线性内存空间必须被映射到物理内存空间中,这个映射关系需要通过使用硬件体系结构所规定的数据结构来建立。我们不妨先称其为映射表。一个映射表的内容就是某个线性内存空间和物理内存空间之间的映射关系。OS Kernel一旦告诉某个CPU一个映射表的位置,那么这个CPU需要去访问一个线性空间地址时,就根据这张映射表的内容,将这个线性空间地址转化为物理空间地址,并将此物理地址送到地址线,毕竟地址线只知道物理地址。
  
  所以,我们很容易得出一个结论,如果我们给出不同的映射表,那么CPU将某一线性空间地址转化的物理地址也会不同。所以我们为每一个进程都建立一张映射表,将每个进程的线性空间根据自己的需要映射到物理空间上。既然某一时刻在某一CPU上只能有一个应用在运行,那么当任务发生切换的时候,将映射表也更换为响应的映射表就可以实现每个进程都有自己的线性空间而互不影响。所以,在任意时刻,对于一个CPU来说,也只需要有一张映射表,以实现当前进程的线性空间到物理空间的转化。
  
  --------------------------------------------------------------------------------
  
  
  
  2. OS Kernel Space & Process Space
  
  
  由于OS Kernel在任意时刻都必须存在于内存中,而进程却可以切换,所以在任意时刻,内存中都存在两部分,OS Kernel和用户进程。而在任意时刻,对于一个CPU来说只存在一个线性空间,所以这个线性空间必须被分成两部分,一部分供OS Kernel使用,另一部分供用户进程使用。既然OS Kernel在任何时候都占用线性空间中的一部分,那么对于所有进程的线性空间而言,它们为OS Kernel所留出的线性空间可以是完全相同的,也就是说,它们各自的映射表中,也分为两部分,一部分是进程私有映射部分,对于OS Kernel映射部分的内容则完全相同。
  
  从这个意义上来说,我们可以认为,对于所有的进程而言,它们共享OS Kernel所占用的线性空间部分,而每个进程又各自有自己私有的线性空间部分。假如,我们将任意一个4 GB线性空间分割为1 GB的OS Kernel空间部分和3 GB的进程空间部分,那么所有进程的4 GB线性空间中1 GB的OS Kernel空间是共享的,而剩余的3 GB进程空间部分则是各个进程私有的。Linux就是这么做的,而Windows NT则是让OS Kernel和进程各使用2 GB线性空间。
  
  --------------------------------------------------------------------------------
  
  
  
  3. Segment Mapping & Page Mapping
  
  
  所有的线性空间的内容只有被放置到物理内存中才能够被真正的运行和操作。所以,尽管OS Kernel和进程都被放在线性空间中,但它们最终必须被放置到物理内存中。所以OS Kernel和所有的进程都最终共享物理内存。在现阶段,物理内存远没有线性空间那么大——线性空间是4 GB,而物理内存空间往往只有几百兆,甚至更小另外即使物理内存有4 GB,但由于每个进程都可以有3 GB线性空间(假如进程私有线性空间是3 GB的话),如果把所有进程的线性空间内容都放在物理内存中,明显是不现实的。所以OS Kernel必须将某些进程暂时用不到的数据或代码放在物理内存之外,将有限的内存提供给当前最需要的进程。另外,由于OS Kernel在任何时候都有可能运行,所以OS Kernel最好被永远放在物理内存中。我们仅仅将进程数据进行换入换出。
  
  从线性空间到物理空间的映射需要映射表,映射表的内容是将某段线性空间映射到相同大小的物理内存空间上。从理论上,我们可以使用两种映射方法:变长映射,和定长映射。变长映射指的是根据不同的需要,将一个一个变长段映射到物理内存上,其格式可以如下(线性空间段起始地址,物理空间段起始地址,段长度)。假如一个进程有3个段:10M的数据段,5M的代码段,和8K的堆栈段,那么就可以在映射表中建立3项内容,每一项针对一个段。这看起来没有问题。但假如现在我们的实际的内存只有32M,其中10M被内核占用,留给进程的物理空间只有22M,那么此进程在运行时,就占据了10M+5M+8K的内存空间。随后当进程发生切换时,假如另一个进程和其有相同的内存要求,那么剩余的22M-(10M+5M+8K)明显就不够用了,这时只能将原进程的某些段换出,并且必须是整段的换出。这就意味着我们必须至少换出一个10M的数据段,而换出的成本很高,因为我们必须将这10M的内容拷贝到磁盘上,磁盘I/O是很慢的。
  
  所以,使用变长的段映射的结果就是一个段要么被全部换入,要么被全部换出。但在现实中,一个程序中并非所有的代码和数据都能够被经常访问,往往被经常访问的只占全部代码数据的一部分,甚至是一小部分。所以更有效的策略是我们最好只换出那些并不经常使用的部分,而保留那些经常被使用的部分。而不是整个段的换入换出。这样可以避免大块的慢速磁盘操作。
  
  这就是定长映射策略,我们将内存空间分割为一个个定长块,每个定长块被称为一个页。映射表的基本格式为(物理空间页起始地址),由于页是定长的,所以不需要指出它的长度,另外,我们不需要在映射表中指定线性地址,我们可以将线性地址作为索引,到映射表中检索出相应的物理地址。当使用页时,其策略为:当换出的时候,我们只将那些不活跃的,也就是不经常使用的页换出,而保留那些活跃的页。在换入的时候,只有被请求访问的页才被换入,没有被请求访问的页将永远不会被换入到物理内存。这就是请求页(Demand Page)算法的核心思想。
  
  这就引出一个页大小的问题:首先我们不可能以字节为单位,这样映射表的大小和线性空间大小相同——假如整个线性空间都被映射的话——我们不可能将全部线性空间用作存放这个映射表。由此,我们也可以得知,页越小,则映射表的容量越大。而我们不能让映射表占用太多的空间。但如果页太大,则面临着和不定长段映射同样的问题,每次换出一个页,都需要大量的磁盘操作。另外,由于为一个进程分配内存的最小单位是页,假如我们的页大小为4 MB,那么即使一个进程只需要使用4 KB的内存,也不得不占用整个4 MB页,这明显是一种很大的浪费。所以我们必须在两者之间进行折衷,一般平台所规定的页大小为1 KB到8 KB,IA-32所规定的页大小为4 KB。(IA-32也支持4 MB页,你可以根据你的OS的用途进行选择,一般都是使用4 KB页)。
  
  --------------------------------------------------------------------------------
  
  
  
  4. Page Table
  
  
  假如使用4 KB的页,那么对于4 GB的线性空间,则需要1,048,576个页表实体,每个表项占用4个字节,则需要4,194,304个字节。仅仅页表就占用4 MB空间,这是一个很大的需求。但如果确确实实一个进程需要使用全部线性空间的话,那么这4 MB的页表空间投入也是必要的。
  
  但在现实中,很少有那个程序需要使用这么大空间,一般的程序往往很小,从几KB到几MB,再使用这么大的页表就纯粹是一种浪费。那我们该怎么办?
  
  一种策略是建立变长页表——我们只建立所需长度的页表。但这种策略带来很大的限制,并且仍然会造成比较大的空间浪费。由于页表机制是使用线性地址作为索引,到页表中进行检索。那么如果我们想让OS Kernel使用C0000000h-FFFFFFFFh,也就是3G

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值