关于内存覆盖技术
接上次的文章,还没有写完,今天就把他补完吧。
1、覆盖技术
内存中通常会分配一个固定区和若干的覆盖区,
不常用的段会放在覆盖区,需要时再调入内存。
覆盖技术只能用于早起的操作系统中,对用户不透明。
2、交换技术
设计思想:内存空间紧张时,将内存中的某些进程暂时换出外存,把外存中某些具备运行条件的进程换入内存。将内存中某些进程暂时换出外存。
暂时换出外存等待的进程状态为挂起状态。刮起状态又分为就绪挂起状态和阻塞挂起状态。
在逻辑上扩充了内存空间。
1、磁盘空间氛围文件区和对换区,换出进程放在对换区,文件区仅存放文件和数据。
2、交换通常在许多进程运行时且内存吃紧时。
内存空间的分配与回收
连续分配管理方式:
1、单一连续分配
内存被分为系统区和用户区
系统区存放内存的低地址部分,用户区存放相关用户数据
内存中只能有一个用户程序,用户程序独占整个用户区空间
优点:实现简单,无外部碎片,可以采用覆盖技术覆盖扩充内存,不一定会用到内存保护
缺点:只能用于单用户单任务的操作系统,有内部碎片**
2、固定分区分配
将整个用户空间分配成若干个固定大小的分区,在每个分区中引入一道作业。
可以采取分区大小相等或者是分区大小不等两种分配方式。
很适用于同一台计算机控制多个相同对象的场合。
操作系统需要建立一个数据结构--分区说明表,来实现对各个分区的分配和回收。
每个表项对应一个分区,通常按照分区的大小来排列。
每个表项包括对应分区的大小、初始地址、状态。
优点:实现简单、无外部碎片
缺点:当用户程序太大,只能使用覆盖技术解决。会产生内部碎片,内存利用率低。
3、动态分区分配
又称为可变分区分配,这种分配方式不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态的建立分区。使得分区的大小正好适合进程的需要。
因此系统分区的大小和数目是可变的。
操作系统记录内存的使用情况:
1、空闲分区表:
每一个空闲分区对应一个表项,表项中包含分区号、分区大小、分区起始地址。
2、空闲分区链
动态分区分配不会预先划分内存分区
动态分配不会产生内部碎片,但是有外部碎片
内部碎片和外部碎片的相关解释在这里给出:
内部碎片:分配给某进程的内存区域中,有些部分没有用上
外部碎片:内存中某些空闲分区由于太小而难以利用
关于解决外部碎片问题
可以通过“紧凑”技术来解决外部碎片。
通过修改进程的起始地址。起始地址保存在进程的PCB中。
关于动态分区分配算法
1、首次适应算法:
从低地址开始查找空闲分区表/空闲分区链,查找到第一个可以适应的内存空间(以地址递增的算法)
2、最佳适应算法
尽可能优先留下大片空闲去,优先使用更小的空闲区,按照容量递增的算法进行排序。
3、最坏适应算法
优先使用最大的连续空闲区,按照容量递减的次序链接,每次分配内存时查找空闲分区表/空闲分区链,找到大小能满足要求的第一个空闲分区。
4、邻近适应算法
每次都从上次查找结束的位置开始检索,找到大小可以满足要求的第一个空闲分区。
优点:算法开销小,不需要对空闲分区大小进行重新排序。
连续分配方式的缺点:
1、固定分区分配、缺乏灵活性,会产生大量的内部碎片,内存的利用率低。
2、动态分区分配,会产生很大的外部碎片,虽然可以通过紧凑技术解决,但是紧凑的时间代价很高。
非连续分配方式(离散分配方式):(分页存储)
把进程需要的空闲分区进行切片分配。
如果分区大小设置越少,则内存空间利用率越高。
将内存空间分为一个个大小相等的分区。
每一个分区是一个“页框“,每一个页框有一个编号,即页框号,页框号从0开始。
将”用户进程“的地址空间也分为与页框大小相等的一个个区域,称为”页“或者”页面“,每一个页面也有一个编号,即“页号”,页号也是从0开始。
操作系统以页框为单位为各个进程分配内存空间,进程的每个页面分配放入一个页框中,也就是说,进程的页面和内存的页框式一一对应的关系。
在这种情况下,可以使用“地址重定位的方法”来进行进程内逻辑地址到无力地址的转换(重定位寄存器存放装入模块存放的初始位置。)
模块在内存中的“起始位置”+目标内存但愿的相对于起始位置的偏移量=绝对地址。
缓冲区溢出时的利用可以参考windows的内存地址随机化可以利用这个进行绕过。
1、要算出逻辑地址对应的页号
2、要知道该页号对应的页面在内存中的起始地址。
3、要算出逻辑地址在页面内的偏移地址。
4、物理地址=页面始址+页面偏移量
页号= 逻辑地址/页面长度
页面偏移量 = 逻辑地址%页面长度
页面在内存中的起始位置:操作系统需要用某种特殊的数据结构来存储.
基本地址变换机构
**用于实现逻辑地址到物理地址的转换的一组硬件机构**
基本地址变换机构可以借助进程的页表将逻辑地址转换成物理地址
通常会在系统中设置一个页表寄存器。存放页表在内存中的起始地址和页表长度
进程未执行时,页表的始址和页表长度放在进程控制块中,当进程被调度时,操作系统内核会把它们放到页表寄存器中。
进程切换相关的内核程序负责恢复进程运行环境。
程序计数器PC负责指向下一条指令的逻辑地址A
页表寄存器存放页表始址和页表长度。
如果页号非法,抛出越界中断,否则通过页号进行计算获得逻辑地址A的页号P和页内偏移量W。可以获得目的页号的内存。
计算获得页号所在的内存块号,从而获得物理地址E。
地址变换:
1、根据逻辑地址计算出页号和页内偏移量
2、判断页号是否越界
3、查询页表,找到页号对应的页表项,确定页面存放的内存块号。
4、用内存块号和页内偏移量的到物理地址。
5、访问目标单元
例子:
若页面大小为L,逻辑地址A到物理地址E的变换过程如下:
1、计算页号和页内偏移量。
2、判断页号是否越界。(合法性检查)和页表长度进行对比。不能大于或者是等于。否则发生中断。
3、页表中页号P对应的页表项地址=页表的起始地址+页号P*页表项的长度。取出页表项内容b。即为内存块号。
页表长度指每个页表项占多大的存储空间,页面大小指的是一个页面占多大的存储空间。
页式管理中,地址是一维的。
具有快表的地址变换机构:
时间局部性:
如果执行了程序中的某条指令,那么不久后这条指令可能再被执行。如果某个数据被访问过,那么这个数据可能被再次访问。
空间局部性:
一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也很有可能被访问。
使用 基本地址变换机构中,每次都要访问一个逻辑地址,都需要查询内存中的页表。由于局部性原理,可能连续多次查到的就是同一个页表项,可以通过快表机制来减少访问页表的次数。
快表:
联想寄存器(TLB)。是一种访问速度比内存快很多的过高速缓存寄存器。
用来存放当前访问的若干页表项。
内存当中的页表常称为慢表。
快表存放页表的一个副本。加快地址转换速度。
若快表未命中,则访问某个逻辑地址需要两次访存。
若快表命中,则节省很多时间。
由于局部性原理,则快表的命中率可以达到90%
两级页表
将长长的页表进行分级。