操作系统:内存管理

一、背景

操作系统:程序的编译、链接、加载、地址绑定

二、交换

进程必须在内存中以便执行,不过进程可以暂时从内存中交换备份存储上(通常是快速磁盘),当需要
再次执行时再调回到内存

  1. 交换算法,如优先级调度算法:低优先级交换出,高优先级交换进;滚出(roll out), 滚入(roll in)
  2. 交换时间(转移时间):转移时间与交换内存空间量成正比

问:将交换出的进程再交换回来的时候,应该调回哪个内存空间

  1. 编译时绑定和加载时绑定。必须回到原位,不可以移动到不同的位置(地址),即运行时不可以发生地址变化
  2. 执行时绑定.可以移动到不同的地址,即运行时可以发生地址变化

三、连续内存分配

内存应容纳操作系统和各种用户进程,因此应尽可能有效分配地址。
本节介绍一种早期方法:连续内存分配。在采用连续内存分配时,每个进程位于一个连续的内存区域,与包含下一个进程的内存相连

1.内存分配

多分区方法:将内存分为多个固定大小分区

可变分区方法:操作系统用表来记录已用和未用内存。开始,整个内存空间是就是一大块的可用空间,称为

  • 可用内存块为分散在内存里的大小不同的孔的集合。每当新的进程载入时,分配足够大的孔。如果孔太大,就分为两块,一块分配,一块回到孔集合。
  • 进程终止时,释放内存,将内存还给孔集合。
  • 如果新孔与其他孔相邻,那么将这些孔合成大孔
  • 系统需要用表来记录已分配孔和未分配孔的信息

从一组可用孔中选择一个空闲孔最常用方法:

  1. 首次适应(first fit):分配首个足够大的孔(最先找到的)
  2. 最佳适应(best fit):分配最小的足够大的孔
  3. 最差适应(worst fit):分配最大的孔

2.碎片

外部碎片
当总的可用内存之和可以满足请求但并不连续时,出现了外部碎片问题。例如:分区大小为2byte、2byte、2byte的不连续的空间,不能分配内存请求为6byte 的进程

内部碎片
进程所分配的内存可能比所需的要大,两个数字只差就是内部碎片。例如:有18464byte大小的孔,要分配内存请求为18462byte, 会剩下2byte 的孔

解决方法:紧缩
移动内存内容,把所有的空闲空间合并成一整块

:紧缩并非总是可能。只适用于动态重定位的时候;不适用于静态定位

四、分段

以用户视角去管理内存的方式,一个程序由多个逻辑段组成
一般组成:主程序、函数、方法、对象、堆、栈、局部变量、全局变量等
在这里插入图片描述

逻辑地址的定义:【分段号, 偏移】
需要段表, 段表条目包括:段基地址、段界限
在这里插入图片描述

五、分页

分页避免了外部碎片和紧缩

1.基本方法

实现分页的基本方法设计将物理内存分为固定大小的块,称为页帧;而将逻辑内存也分为同样大小的块,称为页面

一个页对应一个帧,当需要分配内存时,以页为单位分配内存。若程序大小为n 页,则需要有n 个帧来存放它,而这些帧是不必连续的内存空间

需要掌握空闲空间(空闲帧)信息,为了把逻辑地址转变为物理地址,还需要设置一个页表(页表每个条目是跟页号所对应的帧号)

分页的硬件支持图
在这里插入图片描述
CPU生成的逻辑地址分为两个部分:页码页偏移

  1. 页号(页码)§: 是页表的索引,相应页表中存储着该页所在物理内存的基地址
  2. 页偏移(d): 偏移量,结合基地址形成物理地址

观察下图说明程序员的内存视图如何映射到物理内存。
在这里插入图片描述
可以看出,分页本身是一种动态定位。
采用分页方案不会产生外部碎片:每个空闲帧都可以分配给需要他的进程。但分页有内部碎片,因为进程所要求的内存并不一定是页的整数倍。

在这里插入图片描述

图-空闲帧

2.硬件支持

页表的硬件实现都有多种方法。

  1. 页表可以用一组专用寄存器来保存。但页表非常大时,就不可行了
  2. 将页表放入到内存中,并将页表基地址寄存器指向页表。

若把页表存入内存,会发生什么问题
为了访问数据,需要两次访问内存。第一次查页表,第二次访问地址。需要两次访问内存,这会导致数据访问速度慢

解决的办法:采用高速硬件缓冲,转换表缓冲区(TLB)

TLB中只包含少数页表条目。当CPU产生一个逻辑地址后,把页码发送给TLB。如果找到这个页码,它的帧码也可以立即使用,访问内存;如果不在(未命中),那么就需访问页表。(下图页表应该在内存中)

在这里插入图片描述

3.保护

分页环境下的内存保护是通过每个帧关联的保护位来实现的。

还有一位通常与页表中的每一条目相关联:有效-无效位

  1. 有效位(v)表示相关的页在进程的逻辑地址空间内(合法)
  2. 无效位(i)表示相关的页不在进程的逻辑地址空间内(非法)

4.共享页

分页优点之一是可以共享公共代码。进程的代码可分为可以共享的代码和不可共享的代码,可共享的代码通过共享页表的方式实现。

  1. 可共享的代码- 可重入代码(不能自我修改的代码:他在执行期间不会改变)
    每个进程共享代码段的(页)逻辑地址相同
  2. 不可共享的代码- 私有代码和数据
    针对私有代码和数据的(页)逻辑地址不同

六、页表结构

在把逻辑地址映射为物理地址的过程中,分页方式需要系统维护页表信息。

本节探讨组织页表的一些常用技术,分层分页哈希分页倒置分页

1.分层分页(层次页表)

把逻辑地址编址设为多层次,即多层次的页表。

在这里插入图片描述
p1用来访问外部页表的索引,p2是内部页表的页偏移

在这里插入图片描述
在这里插入图片描述

图-二级页表方案

采用层次结构页表存储结构有什么优点?

  1. 可以实行页表的不连续存储
  2. 可以节约内存空间

那么问题来,为什么可以节约内存空间,进程要维护的页表大小是多少
假设一个系统具有32位逻辑地址空间和4K大小的页,每个页条目大小4byte。

那么,我们为覆盖4Gb的内存,每个进程要维持4Mb的页表

  1. 页表条目的数量 232/212=220
  2. 需要的页表大小220X 4byte = 4Mb

如果页表是两层结构,同样的条件下,对页表进行再分页,页码分为10位页码和10位页偏移,那么,为覆盖4Gb的内存,进程要维护的页表大小是多少

进程要维护的页表大小是不确定的,这与进程所要占用的内存大小有关,例如:

如果某个进程要占用210×4byte,那么需要1个外部页(大小为210× 4byte)表到1个页表的页(大小为210× 4byte)。
如果某个进程要占用210×4byte × 2,那么需要1个外部页表到2个页表的页。
极端情况下,进程占用全部内存,需要1个外部页表到210个页表的页。
所以一般情况下采用分层更节省空间

2.哈希页表

处理超过32位地址空间的常用方法是使用哈希页表

逻辑地址的定义为【虚拟页码,偏移量】把虚拟页码作为哈希值(key)

  • 哈希页表的每一条目是链表,链表的每个元素包括 【虚拟页码,所映射的帧号,下一个元素指针】
  • 根据虚拟页码(哈希值)找到匹配的条目,并在链表里找到相对应的帧号

通过页号转换到哈希表中,用链表指针找到想对应的帧号,并用帧号和页偏移形成物理地址
在这里插入图片描述

3.倒置页表(反向页表)

为了减少页表消耗的内存空间而采用的方法
即,整个系统只有一个页表,页表对于每个真正的内存页或帧才建立一个条目

反向页表编址:【进程标识符,页码,页偏移】

  • 地址信息:需要用页码和页偏移来确定空间
  • 进程信息:需要用进程标识符确定进程信息

在这里插入图片描述

参考

《操作系统概念》

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值