加载中…
正文 字体大小:

学习笔记--操作系统 存储器管理1

(2014-11-28 10:28:42)
标签:

it

学习了操作系统这门课,杜炳阳同学和学长们也多次讨论过存储器管理这一块,所以想做个整理。


在计算机系统存储层次示意中,高速缓存、主存和磁盘缓存被统称为主存;磁盘和可移动存储介质被称为辅存


1.物理内存:真实存在的插在主板内存条的容量的大小。


2.计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组。每字节都有一个唯一的虚拟地址(或主存由若干个存储单元组成,每个存储单元有一个编号,这种编号可唯一标识一个存储单元)。这个唯一的虚拟地址是作为到数组的索引的。


3.物理寻址CPU通过使用物理地址来访问存储器叫做物理寻址(早期的物理寻址方式:当CPU执行加载指令时,它会产生一个有效物理地址,通过存储器总线,把它传递给主存。主存取出从得到的物理地址处开始的取相应的内容,并将相应的内容返还给CPUCPU会将它存放在一个寄存器里)。


4.逻辑空间源程序经过汇编或编译后,形成目标代码,每个目标代码都是以0为基址顺序进行编址的,原来用符号名访问的单元用具体的数据——单元号取代。这样生成的目标程序占据一定的地址空间,称为作业的逻辑地址空间,简称逻辑空间


在逻辑空间中每条指令的地址和指令中要访问的操作数地址统称为逻辑地址。即应用程序中使用的地址。要经过寻址方式的计算或变换才得到内存中的物理地址。

逻辑地址就是源程序里使用的地址,或者源代码经过编译以后编译器将一些标号,变量转换成的地址,或者相对于当前段的偏移地址。


程序的装入和链接:

一个用户源程序变为可在内存中执行主要要经过三大步骤:

1.编译——编译程序将用户源代码编译成若干目标模块

2.链接——链接程序将编译后形成的一组目标模块,以及它们所需要的库函数链接在一起,形成完整的装入模块

3.装入——装入程序将装入模块装内存。

 

程序的装入

1.绝对装入方式:绝对装入程序按照装入模块中的地址,将程序和数据装入内存。装入模块装入内存后,程序中的逻辑地址与实际内存地址完全相同。绝对转入方式只能将目标装入到内存中事先指定的位置。适用于单道程序环境。


2.可重定位装入方式:在多道程序环境下,所得到的目标模块的起始地址通常是从0开始,程序中的其他地址也都是相对于起始地址计算的。此时应采用可重定位装入方式,根据内存的当前情况,将装入模块装入到内存的适当位置。


 

如图:

学习笔记--操作系统 <wbr>存储器管理1

把程序中指令和数据的相对地址与本程序在内存中的起始地址相加,才能得到正确的物理地址。

通常把装入时对目标程序中指令和数据的修改过程成为重定位


如果地址变换在装入时一次完成,以后不再改变,那么叫做静态重定位

适用范围:多道程序环境

 

不适用:程序运行时在内存中移动位置(程序在内存中的移动,那么它的物理位置会发生了变化)。

 

优点:无需硬件支持

缺点1.程序重定位之后就不能在内存中搬动了

    2.要求程序的存储空间是连续的,不能把程序放在若干个不连续的区域中。


1.动态运行时装入方式:当程序运行时在内存中移动位置,那么可以采用动态运行时装入方式。


动态运行时的装入程序在把装入模块装入内存中,并不立即把装入程序的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行。因此,存入内存后的所有地址都仍是相对地址。为了使地址转换不影响指令的执行速度,这种方式需要一个重定位寄存器的支持。


优点1)目标模块装入内存时无需任何修改,因而装入之后再搬迁也不会影响其正确执行,这对于存储器紧缩、解决碎片问题是极其有利的;

 2)一个程序由若干个相对独立的目标模块组成时,每个目标模块各装入一个存储区域,这些存储区域可以不是顺序相邻的,只要各个模块有自己对应的定位寄存器就行。

缺点:需要硬件支持。


程序的链接:

根据链接时间的不同,可以把链接分为三种:

1.静态链接:在程序运行之前,先将各目标模块及它们所需的库函数,链接成一个完整的装配模块,以后不再拆开。一般需要解决的问题有:对相对地址进行修改和变换外部调用符号。

2.装入时动态链接:将用户源程序编译后所得到的一组目标模块,在装入内存时,采用边装入边链接的链接方式。优点:便于修改和更新,便于实现对目标模块的共享

 

3.运行时动态链接:对某些目标模块的链接,是在程序执行时需要该(目标)模块时,才对它进行的链接。


虚拟存储器:

虚拟内存:计算机系统内存管理的一种技术,它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。


虚拟地址每个进程可以直接寻址的地址空间,不受其他进程干扰。每个指令或数据单元都在这个虚拟空间中拥有确定的地址。   

   

虚拟寻址CPU通过生成一个虚拟地址来访问主存,这个虚拟地址在被送到存储器之前先转换成适当的物理地址。将一个虚拟地址转换成为物理地址的任务叫做地址翻译。地址翻译需要CPU硬件和操作系统之间的紧密合作。CPU芯片上叫做存储器管理单元MMU的专用硬件,利用存放在主存中的查询表来动态翻译虚拟地址,该表的内容是由操作系统管理的。


线性地址空间:如果地址空间中的整数是连续的,那么我们说它是一个线性地址空间。

在一个带虚拟存储器的系统中,CPU从一个有N=2n个地址的空间中生成虚拟地址,这个地址空间称为虚拟地址空间

 

根据虚拟寻址的过程,我们发现通过虚拟地址转到物理地址最重要的一步就是地址翻译了。

如图:

学习笔记--操作系统 <wbr>存储器管理1

地址翻译过程图:


学习笔记--操作系统 <wbr>存储器管理1

想要能够明白这个图,需要了解不少知识:

概念上而言,虚拟存储器被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。每个字节都有一个唯一的虚拟地址,这个唯一的虚拟地址是作为到数组的索引的。磁盘上数组的内容被缓存主存中。


和存储器层次结构中其他缓存一样,磁盘(较低层)上的数据被分割成块,这些块作为磁盘和主存(较高层)之间的传输单元。虚拟存储器系统通过将虚拟存储器分割为大小固定的块(虚拟页)来处理这个问题。每个虚拟页的大小为P=2p个字节。


物理存储器被分割成大小固定的块(物理页或页帧),大小页为P字节。

 

比如说:

学习笔记--操作系统 <wbr>存储器管理1

在磁盘上有N个连续的字节大小的单元组成的数组成为虚拟存储器,虚拟存储器系统将它分割称为8个块,也就是虚拟页。虚拟页有三个状态,分别是:未分配的、缓存的和未缓存的


未分配的:虚拟存储器系统还未分配(或创建)的页。未分配的块没有任何数据和它们相关联,因此也就不占任何磁盘空间。


缓存的:当前缓存在物理存储器中的已分配页。


未缓存的:没有缓存在物理存储器中的已分配页。


然后可以看到虚拟页03没有被分配,虚拟页146被缓存在了物理存储器中,虚拟页257被分配了,但是当前并没有缓存在主存中。


地址翻译的过程就是把虚拟地址转成物理地址,需要实现它就是说明虚拟地址和物理地址之间存在一个映射,而实现这个映射就需要一个很重要的存放在物理存储器中的数据结构叫做页表(页表就是将虚拟页映射到物理页)。每个虚拟页在页表中都有一个页表条目

页表条目的数据结构(有效位+n位地址字段)

 

学习笔记--操作系统 <wbr>存储器管理1

有效位:表示该虚拟页是否被缓存在DRAM中,如果设置了有效位,那么地址段就为物理页号,如果没有则表示该虚拟页没有缓存在内存中,那么这个地址段就指向该虚拟页在磁盘上的起始位置或者还未分配。


页表就是页表条目的数组。而每个进程都有一个独立的页表

学习笔记--操作系统 <wbr>存储器管理1


地址结构(页号+位移量)为:

学习笔记--操作系统 <wbr>存储器管理1

虚拟地址结构包括虚拟页号(VPN)虚拟页面偏移量(VPO)(或成为虚拟页面页内地址),同样物理地址结构也是包括物理页号(PPN物理页面偏移量(PPO


地址翻译中,MMU利用页表来实现虚拟地址到物理地址的映射。处理器会生成一个虚拟地址,并把它串送给CPU中的MMU。虚拟地址中包含了虚拟页号VPN。所以,首先CPU中会有一个控制寄存器叫做页表基址寄存器指向了当前页表。MMU利用虚拟地址中的虚拟页号(VPN)来选择页表条目(PTE),例如,虚拟页号0选择页表条目0,虚拟页号1来选择页表条目1。找到页表条目后,如果根据有效位的判断,该虚拟页缓存在了主存中,那么就可以根据页表条目找到该虚拟页缓存在哪个物理页号中了。然后再根据物理页号和虚拟地址中的虚拟页面偏移量串联起来,就可以得到相应的物理地址。物理页面偏移量和虚拟页面偏移量是相同的。这样就实现了虚拟地址映射到物理地址的过程。


整个CPU硬件执行的步骤为:

1.处理器生成一个虚拟地址,并把它传送给MMU

2.MMU生成PTE地址,并从高速缓存/主存请求得到它

3.高速缓存/主存向MMU返回PTE

4.MMU构造物理地址,并把它传送给高速缓存/主存(此步虚拟地址转换成物理地址)。

5.高速缓存/主存返回所请求的数据字给处理器。


但是这是基于根据虚拟页号找到的页表条目中的有效位表明该虚拟页缓存在物理存储器中了。如果没有缓存在物理存储器,那么这个现象就叫做缺页

 

如果从有效位的判断可以得到该虚拟页没有被缓存,那么会触发一个异常,叫做缺页异常。缺页异常调用内核中的缺页异常处理程序,该程序会选择一个牺牲页。选择牺牲页的算法有最佳置换算法(理想化),先进先出页面置换算法,最近最久未使用置换算法,Clock置换算法等。如果选择的牺牲页中的内容已经被修改过了,那么内核就会将它拷贝回磁盘,内核修改牺牲页的页表条目,反映出虚拟页不在缓存在主存中这一事实。然后内核从磁盘拷贝原来没有缓存在物理存储器中的虚拟页到物理存储器中,更新相应的页表条目然后缺页异常处理程序返回


当异常处理程序返回时,它会重新启动导致缺页的指令,该指令会把导致缺页的虚拟地址重新发送到地址翻译硬件。而此时地址翻译硬件可以在主存中找到该虚拟页的缓存,所以可以正常处理了。

 

 

过程图如下:

 

学习笔记--操作系统 <wbr>存储器管理1

1.处理生成虚拟地址VAMMU

2.MMU生成PTE地址,并从高速缓存/主存中得到它

3.高速缓存/主存向MMU返回PTE

4.MMU构造物里地址的时候,发现缺页。产生了异常,调用异常处理程序(异常处理里程序可以分析出此时是缺页异常)

5.缺页处理程序确定出物理存储器中的牺牲页,如果这个牺牲页已经被修改了,则需要拷贝回磁盘上

6.缺页处理函数将需要的虚拟页缓存到主存中,并更新存储其中的PTE

 

7.缺页处理程序返回到原来的进程,再次执行导致缺页的命令。CPU将引起缺页的虚拟地址重新发送给MMU。因为虚拟页面现在缓存在物理存储器中了,所以就会命中,然后就可以正常继续执行下去了。


Linux中怎么处理缺页呢?


MMU在试图翻译某个虚拟地址A时,触发了一个缺页,然后异常控制会转移到调用缺页处理程序。缺页处理程序会执行下面的步骤:

1.判断虚拟地址A是否合法。如果不合法就是触发一个段错误,从而终止这个程序。

2.判断试图进此的存储器访问是否合法。就是判断进程是否有读、写或者执行这个区域内页面的权限。如果是不合法的,那么缺页处理程序会触发一个保护异常

3.如果虚拟地址合法并且存储器访问合法,那么内核就知道这是个合法的虚拟地址并且操作是合法的。

4.缺页处理程序就会根据页面置换算法选择一个牺牲页,将它交换出去,换入新的页面并更新页表。

 

5.当缺页处理程序返回时,CPU重新启动引起缺页的指令,这条指令将再次发送AMMU。这次MMU就可以正常地翻译A了,而不会再产生缺页中断了。


快表:


页表是放在内存中的,MMU从主存中得到页表和根据页表条目得到物理地址后再次访问主存得到数据,所以说CPU在每存取一个数据的时候需要两次访问主存。后来,人们就想可不可以通过一次访问主存就可以得到数据,于是,人们想到了增设一个寄存器,叫做特殊高速缓存寄存器(联想寄存器或者快表,在IBM系统中被称为TLB)用以存放当前访问的那些页表项,所以它就是一个关于页表条目的缓存,并且缓存在CPU中,这样就可以加快CPU存取数据的速度了。

 

 

快表是一个小的、虚拟寻址的缓存,其中每一行都保存着一个由单个页表条目组成的块。


学习笔记--操作系统 <wbr>存储器管理1

此时地址变换过程是:在处理器生成了一个虚拟地址,并把它传递给MMUMMU快表中取出相应的PTEMMU将这个虚拟地址翻译成一个物理地址,并且将它发送给高速缓存/主存。最后高速缓存/主存将所请求的数据字返回给CPU


这是快表中有该虚拟页的页表条目,如果没有的话,那就叫做快表没有命中。那么就需要去访问内存中的页表了,找到后,把从页表项中读出的物理块号送地址寄存器;同时,再将此页表条目存入快表的一个寄存器单元中,重新修改快表。如果快表已满,则OS必须找到一个牺牲页表条目,将它换出去。

 

 

现在的大多数计算机,都支持非常大的逻辑地址空间。如果我们有一个32位的地址空间,4KB的页面和一个4字节的页表条目,那么在内存中我们需要一个4MB的页表。所以人们想要压缩页表,而压缩页表的常用方法是使用层次结构的页表


两级页表:


 

假设在一时刻,虚拟地址空间有如下形式:存储器的前2K个页面分配给了代码和数据,接下来的6K个页面还未分配,再接下来的1023个页面也未分配,接下来的1个页面分配给了用户栈。

学习笔记--操作系统 <wbr>存储器管理1

一级页表中的每一个PTE负责映射虚拟地址空间中一个4MB的片,这里每一片都是由1024个连续的页面组成的。比如,PTE0映射第一片,PTE1映射接下来的一片,以此类推。二级页表中的每一个PTE都负责映射一个4KB的虚拟存储器页面。


 

二级页表的逻辑地址(32位逻辑地址空间)


学习笔记--操作系统 <wbr>存储器管理1

二级页表的思想就是将页表进行分页,并离散地将各个页面分别存放在不同的物理块中。所以我们需要为离散分配的页表再建立一个张页表,就叫做外层页表,在每个页表条目中记录了页表页面的物理块号。

 

在地址变换机构中需要增设一个外层页表的寄存器,用于存放外层页表的起始,并利用逻辑地址中的外层页号,作为外层页表的索引,从中找到指定页表分页的起始,再利用P2作为指定页表分页的索引找到指定的页表条目,其中即含有该页在内存的物理块号,用该块号和页内地址即可构成访问的内存物理地址。


 

在采用两级页表结构的情况下,对于正在运行的进程,必须将其外层页表调入内存,而对页表则只需要调入一页或几页。


学习资料:

博客:http://blog.csdn.net/hguisu/article/details/5713099

《计算机操作系统》西安电子科技大学出版社

《深入理解计算机系统》 机械工业出版社



0

阅读 评论 收藏 转载 喜欢 打印举报
已投稿到:
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有