zoukankan      html  css  js  c++  java
  • 存储(第二部分)

    虚存管理:

    1.页式存储管理.

    2.段式存储管理.

    3.断页式的存储管理.

    4.局部性的原理.

    页式存储管理将一个地址分为了两个部分,一个部分是页号,另一个部分是页内地址.一个用户程序它有逻辑地址,每一个逻辑地址可以根据页划分页的大小,分出页号和页内地址两个部分.为什么要对这个程序进行分页呢?开始我们在讲这个实存的时候也提到了这一点,其实虚存它的一个理念也就是利用有限的资源尽可能的执行大一些的程序.因为在实存管理当中是不可能达到这样的一个效果的.

    也就是说,如果你内存只有64KB,我要执行128KB的程序这是绝对不允许的.因为内存无法一次将这个用户的程序调入进来,由此我们就提出了虚存.虚存的理念就是通过对这个用户程序和内存进行分块,然后通过用户程序一块一块的拿到内存里面来,这样一来执行完的先调入内存执行完的又马上退出内存让没有执行的块调入内存来执行.这样就使得内存执行比它大一些的应用程序成为了可能.

    所以说页式存储就是基于这种理念而产生的.

    我们把应用程序和内存分别地分块,也可以说是分页,然后用户程序我把它分成了N个页面,然后内存根据我用户程序分的页面的大小也进行分页,因为这个内存到时候你每一个块是要读入一个页面的,所以用户程序分页的大小和内存分页的大小应该要是一样的,否则就会出错.然后将用户程序分了页之后就按一定的要求将这个页一个一个的映射到内存当中来.这个页表就是起记录的作用,它记录了用户程序到内存当中的页号的对应表,因为在内存当中是从0开始分块,可以说是分页,比如说这里分了11个页,用户程序这里也分了十几个页,然后用户首先将这个0号页调入内存,内存一检查2号是空的,还没有页面的,所以就将这个0号页装入了内存的2号块当中.

    根据这个页表我们就可以直观地查询到这个对应关系.就是目前用户程序的第0块对应的是内存当中的第2块,而用户程序的1号页就是调入了内存的3号页面,这样子就产生了一个对应.


    页式存储地址转换的图:

    用户程序当中分的这个页是逻辑的页的性质,然后它所用到的地址是逻辑的地址,而映射到内存当中之后就是一个实在的地址了.0号页是映射到了内存当中的2号,而不是内存当中的1号,这样子就产生了一个问题,用户程序的逻辑地址如何和内存当中的实际地址进行一个转换的过程.

    这个图就描述了转换要走一个什么样的流程.逻辑地址L分为了两个部分:一个是页号,一个是页内地址.页号和页内地址它们的长度是如何来确定的?

    假设用户程序有16KB,而每一个页面分为2KB大小,这样子这个用户程序就会有8个页面.用户程序的总大小就决定了用户程序它的逻辑地址空间的大小.要记录16KB的数据,地址空间要2的K次方=容量16KB.通过这个算式的计算我们计算得知K是等于14.我要存储16KB的数据,需要14位的地址空间.所以总的地址空间的大小是14位.14位地址空间中多少位用于页内地址多少位用于页号呢?这取决于页的大小了.

    页的大小是2KB,所以页内地址需要11位的地址空间.因为2的11次方=2KB.那么页内地址应该就是从0-10位,11位空间.那么页号就是3位的页号.所以页号是3位,页内地址是11位.

    知道了逻辑地址L的页号和页内地址怎么求之后,现在是给你一个完整的逻辑地址,让你求出物理地址.

    流程是这样子的:

    首先取出它的页号,得到这个3的逻辑页号,我们就根据这个逻辑页号去查找这个内存的块号,逻辑页号为3,对应的内存块号为b.当然b是一个地址,是一个二进制的地址.然后用这个地址作为高位,页内地址不变,两者拼合,这样子就形成了物理地址.


    页式存储的优缺点:


    软考中页式存储管理的真题:

    逻辑地址8644转为物理地址是多少?逻辑地址到物理地址它们有一个什么样的关系?要如何求物理地址?首先将逻辑地址分为两部分,页号和页内地址,

    其实这是一个非常容易的、格式也非常标准的一个页式存储的题.但是最大的问题是它牵涉到一个二进制和十进制之间的一个转换.因为我们开始提到的地址可以分为两部分,多少位为页内地址,多少位为页号.这个逻辑地址的位数8644不是相对于十进制数而言,而是相对于一个二进制数值而言的.所以要做这个题目首先就要把逻辑地址化为二进制.

    8644化为二进制是10000111000100,哪一部分是页号,哪一部分是页内地址.页内地址的位数/长度取决于你页面的大小.要将页面的大小化为2的N次方形式,求出N,也就求出了页内地址它的位数.页内地址大小是4KB=2的12次方,所以页内地址应该有12位.除了页内地址的就是页号了,根据页号我们要进行查表,查表得到内存的块号,刚才的页号是10,二进制的10转化为十进制是2,所以可以得知物理块号是8.8化为2进制是1000.所以把块号和页内地址拼接起来就是1000 0001 1100 0100,化为十进制是33220.


    段式存储管理的地址的形式和页式存储是非常相似的.段式存储就是从用户的角度,注意是从用户的角度出发,将一个程序分为多个段,大家可以注意到的一点就是这个段的长度,段的长度一般会比页的长度、页的大小大的多.另外一方面还应该要注意它和页式存储的一个区别,页式存储当中任何一个页它的大小是相等的,但是段式存储管理当中段的大小是不等的.这是和页式存储很大的一个区别.它的理念和页式存储管理也有点相似,也是把这个存储块,把这个用户的一个作业空间或者说是用户的进程分为多个块.然后再把这个块再分别的读到内存当中.就是它这个段大小比较大一点,然后段的大小它不是恒定的,有大的段也有小的段.

    段式存储当中它的地址计算和页式的也是非常相似的.一个地址它的段号是2号,偏移量是100.如果我们要求这个实在的物理地址,那就取出这个段号,和段表的起始地址相加.然后找到对应的表项,段号为2号的,它的基址为8KB,用8KB和这个偏移量进行相加,也就是一个拼接的一个过程,就得到了物理地址.

    为什么段式存储的内存碎片浪费大呢?主要因为我们段的大小会大一些,就等于是在内存当中老在分类一些大的块,然后大的块之间的这些小的块就是被浪费掉的.而相比之下,页式存储的利用率高,产生的内存碎片小,为什么呢?因为页式存储的页分的细一些,很小很小一个的页,2KB、2KB一个,这样子每次的这个碎片,碎片的大小就是小于2KB了.


    3、段页式的存储

    段页式的存储的提出是有原因的.这是因为段式存储和页式存储它们都有不足的地方.段式存储它是从用户的角度去进行分割的,分割的块比较大,但是那些块都是有实在含义的块,你比如说一个程序它可以分为程序的执行段、程序的数据段,一块一块的,然后它这种形式便于共享.共享主要体现在什么方面呢?就是在一个多用户的操作系统当中,它可能有多个用户同时运行了一个程序.然后对于多个用户而言,这些程序感觉上是独立的,如果我们进行段式的一个存储那么程序,我们知道程序的执行部分它不会改变的.程序还有一块是用户的数据区域,那么我们可以将程序区域和数据区域分别分为程序段和数据段,也就是说一个程序我把它分为程序段和数据段,数据段是大家的数据不同,内容不同,而程序段都是相同的.所以当有多个人运行这样的程序的时候,在我们的主存空间当中,就只要出现一个程序段和多个数据段.这样子就可以避免同样的一个程序段在内存当中运行多次耗费资源,这样子就实现了资源的共享.但是这样一种形式我们刚才也讲过了,由于它程序段比较大,所以可能造成内存资源的浪费.而页式存储能够很好地解决这个问题.

    在页式存储当中内存被划分成了很多很多很小的块,然后程序也被划成很多很多很小的块,这样子一来它的程序内存的空间就能够得到足够充分的利用.因为每一个内存当中的一个小块,它都是合法的能被其他的程序所应用的块.

    而段页式存储就综合了它们的优点,它将程序先分段再分块,然后每一个段它就对应了一个页表,一个程序它有一个段表,这样子一来程序的每一个的段它所要求的内存块可以是不连续的块.

    你比如说一开始提到段式存储的时候,每一个段它都是分的操作系统当中连续的块,这里面段与段之间的空隙就是被浪费掉的内存空间,

    如果采用段页式那就不存在这个问题了.页表是一个页号与内存块的对应表,然后存储块可以是零散的,这样子就可以产生一个很好的一个影响,也就是说我们可以把这个页表看成是一个连续的存储空间,它是一个段,但是实际上它可以使用不连续的物理内存.这样子既充分利用了内存,又使有意义的这些程序段被划分成了一个一个的段,使它们功能独立的段.所以说用这个段页式的存储它两方都兼具了.是一种很方便的一种方式.

    段页式存储空间浪费小,它里面其实最终还是把主存进行了分页,分了很多很细的页面,这样子就使主存能够得到充分的利用.存储共享容易是因为一个程序被分成了多个逻辑的段,这些段都是有意义的,当多个用户运行这些进程的时候,它这些一个段一个段可以被共享.

    但是段页式存储也有缺点,就是因为又有段表又有页表,它一个地址空间的转换可能需要进行几次的计算,从逻辑地址转成物理地址它要经过几次的计算,这样子一来就大大增加了系统的负荷,就使得执行速度降低一些.


    例子:

    段页式存储,页是对这个实存和程序都划分的,而段就是对逻辑,就是一个逻辑上的概念,是对程序划分的,是用户角度的.而实存,是这个操作系统角度,系统角度的.页一般是系统的划分,而段就可以人为地进行一些操作了.

    对于一个程序,它应该是有一个段表和一组页表,因为段表的每一个段它要对应一个页表.所以说一个程序它应该是要对应一个段表和一组页表.

    每道程序其实还需要一个基号的.其实这个基号它和这个段号、页号它有点相似之处,只是说它的范围会广一些.它这个系统里面有这么一个表格,然后系统的每一个程序它分配了一个基号,基号对应的有一个段的起始号,因为就这个内存而言它可能有很多个段,从1号开始排起可能有好几百个段,而对于某一个程序而言它们的段号编号应该都是从0开始的.等于它这个程序内部的段号是一个逻辑段号,而外面的这个段号是一个物理段号,如果说你要准确地定位它的地址,就必须要把逻辑的段号转化为物理的段号.

    最难的是逻辑地址向物理地址的一个转换过程

    逻辑地址:21-20位x是基号.

    求解这一个问题必须了解系统对这些概念的一个组织方式.

    系统有一个基表,然后接下来有段表,最后有页表.它们的组织方式是这样子的:基号是给的用户进程的一个编号,就是每一个用户进程它会有一个识别用户的一个编号.就相当于给用户分配了一块内存,当然这个表中还有其他的选项就没有一一列出来了,它有这个段的起始位置.

    比如说我给张三就分配了系统当中的1-5这个段给他使用,而李四就分配了6-20这个段号给他使用.而王五我给他21-100这个段号给他使用.通过基号我们可以查询到段的起始号.把段的起始号和逻辑段号进行拼接可以得到页表的起始位置,找到页表的起始位置然后这个就对应了一个页表.页表里面有很多个表项,然后页表的表项就和内存的块是相对应的,所以最终就找到了内存的块号.然后把块号和页内地址进行拼接就得到了物理地址.

    所以说这个工作要一步一步地下来,一层一层地下来.首先是根据基号,取址取到段的起始号,再将这个段的起始号和逻辑段号进行拼接,拼接好之后就取出这个页表的起始地址.页表起始地址和这个页表的某一块的逻辑地址进行拼接,拼接好之后取到这个内存块.取到内存块就将内存块号和这边的地址进行拼接,块号是高位,页内地址是低位.

    这样子最后一问也就得出了答案:

    (((x)+s)+p)*2^11+d

    首先从基号取出一个段的起始地址,再与段相加取出一个页表的地址,页表的起始地址加这个逻辑的页号,就能够得到一个内存块号.内存块号这个实际上是一个移位的过程,也就是说如果我得到的内存块号是11011,把它与另外一个二进制数1111进行拼接,把它放在1111的前面,那么我们就首先要在11011后面补四个0再与这一个1111相加就可以达到拼接的效果.那么我们这一个乘以2的11次方也就是这个效果这是因为如果说它后面要拼四位的数我就乘以2的4次方,就使后面得到四个零,就拼接四位.如果它后面要拼接11位的数,那么我们就乘以2的11次方让它后面多出11个0和11位的数相加就得到了完整的地址.


    页面置换算法是做什么用的呢?前面已经提到过,在页式存储当中,内存的数量是可以少于待运行的程序的数量的.也就是说,内存如果只有四个页面,而程序有10个页面,这样的程序也是可以执行的.那么在它的执行过程中就会有一个问题,例如1、2、3、4块程序都已经装入了内存,当第五块程序要装入内存的时候,1、2、3、4块当中就必须要有一块让出空间来,而让第五个页面进来.否则程序就无法顺利地执行,然而这一个过程就称为页面置换.而页面置换算法的一个作用就是说,利用什么样的策略,将内存中的页面换出来,如果说内存中有4个页面我该先淘汰哪一个页面会比较合适.这样子就有三种常用的页面置换算法.

    最优算法

    先进先出算法

    最近最少使用算法


    例题:

    其实求缺页次数就要求我们了解这个缺页的一种处理方式.

    先进先出算法的思想是:哪一个页面先进入内存,淘汰的时候就先将它送出内存,先将它淘汰.这就是先进先出.

    首先访问的是一号页面,此时的内存块1、2、3这三个内存块都是空闲的,

    虽然这三个页面都是直接读没有置换出的页面来但是它们也属于缺页.因为缺页就是这样子的一个概念,只要是内存都没有就算是缺页.所以前三个页面调入的时候它也算是缺页的现象.

    读5号页面此时就涉及到页面置换的算法了.因为5号页面进入的时候内存的三个块都已经被填满了,被填满了我们就要确定哪一个页面应该要被淘汰出来.

    5号页面刚好在内存当中,所以不涉及到这个页面置换.接下来访问2号页面,

    缺页次数比较高了.

    最优置换算法:它就判断后面哪些页面要最近被使用到,你比如说4号页面就在第6次的时候要用到.6号页面从此以后不再要用到了,所以它就把这个以后不要用到的这个页面给淘汰掉了.而把最近会要访问到的一些页面留下了.这就是最优置换算法它的一个处理的一种方案.就是查看后面的序列看哪些页面先将被使用到就留哪些页面,而后被使用到的页面就先把它去掉,这个还是比较科学的.

    最近最少使用算法:

    因为它判断一个页面是不是很长时间没被使用过了,很长时间没被使用过它也有可能以后也不会被使用到,那我们先淘汰这样的页面.等到5进入的时候,5进入的时候我们就要进行判断了,1、4、6这三个页面哪个最长时间没被访问.6刚刚被访问了,4是在6之前被访问的,而1是在4之前被访问的.1是最久没被访问的一个页面,所以1被淘汰了.

    最佳适应算法它的缺页次数确实是比其他的几种算法要少一些.所以才称它为最优.


    一个原理:局部性原理.

    这个原理非常的重要.其实分页这种存储分配方式,它的提出与这个局部性原理有着密切的关系.局部性原理分为时间的局部性和空间的局部性.

    时间的局部性:如果说一个程序它的某一条指令刚刚被执行完,那么它很有可能在不久的将来又要被使用到.或者是某一个数据被访问完,它有可能立即就要被再次访问.

    空间局部性:一段程序访问了某个存储单元,这个程序它有可能在不久之后访问这个存储单元周边的一些存储单元.

    第一个定义语句只要执行一次而已,输出结果的也只要执行一次而已.这里面存在着巨大的差异.s+=j;要执行1000*1000次,100万次.

    当然我们不可能把一个语句分成一个页面,那是不可取的.假如把数据的定义部分分成一个页面,而同时把输出结果的也分成一个页面,把中间的循环分成另外一个页面,那么这一个时间局部性就体现的很明了了.

    这一个页面要被执行很多很多次,而有些页面只要执行一次就够了.

    也就是有这一个理论为基础,我们的页式存储才能够得到那么高的效率.其实如果页式存储它的缺页率非常非常高的话,也就是说任何一个页面它要使用到的次数是一个平均值的话,那么页式存储可能效率非常非常低.但是正是因为有这种局部性的原理在里面,它一个程序可能只有10%到20%的语句要经常的使用到,所以说内存只要分配给一个程序20%或者是30%的,占它程序20%到30%的内存就已经够用了.

    所以局部性这个原理非常的重要.

  • 相关阅读:
    PHP+shell实现多线程的方法
    【JavaScript】一个同步于本地时间的动态时间
    void 0 或者 undefined
    Android Activity间动画跳转
    如何申请微信公众平台接口測试帐号
    hdu 4862 KM算法 最小K路径覆盖的模型
    【Unity 3D】学习笔记三十三:游戏元素——天空盒子
    cocos2d-x-lua基础系列教程五(lua单例)
    技术走向管理一些思考(7)-激励成员
    Runtime.getRuntime().exec()----记录日志案例
  • 原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/7202183.html
Copyright © 2011-2022 走看看