一、背景
二、交换
进程必须在内存中以便执行,不过进程可以暂时从内存中交换
到备份存储
上(通常是快速磁盘),当需要
再次执行时再调回到内存
- 交换算法,如优先级调度算法:低优先级交换出,高优先级交换进;滚出(roll out), 滚入(roll in)
- 交换时间(转移时间):转移时间与交换内存空间量成正比
问:将交换出的进程再交换回来的时候,应该调回哪个内存空间
?
- 编译时绑定和加载时绑定。必须回到原位,不可以移动到不同的位置(地址),即运行时不可以发生地址变化
- 执行时绑定.可以移动到不同的地址,即运行时可以发生地址变化
三、连续内存分配
内存应容纳操作系统和各种用户进程,因此应尽可能有效分配地址。
本节介绍一种早期方法:连续内存分配。在采用连续内存分配
时,每个进程位于一个连续的内存区域,与包含下一个进程的内存相连
1.内存分配
多分区方法
:将内存分为多个固定大小分区
可变分区方法
:操作系统用表来记录已用和未用内存。开始,整个内存空间是就是一大块的可用空间,称为孔
。
- 可用内存块为分散在内存里的大小不同的孔的集合。每当新的进程载入时,分配足够大的孔。如果孔太大,就分为两块,一块分配,一块回到孔集合。
- 进程终止时,释放内存,将内存还给孔集合。
- 如果新孔与其他孔相邻,那么将这些孔合成大孔
- 系统需要用表来记录已分配孔和未分配孔的信息
从一组可用孔中选择一个空闲孔最常用方法:
- 首次适应(first fit):分配首个足够大的孔(最先找到的)
- 最佳适应(best fit):分配最小的足够大的孔
- 最差适应(worst fit):分配最大的孔
2.碎片
外部碎片
:
当总的可用内存之和可以满足请求但并不连续时,出现了外部碎片问题。例如:分区大小为2byte、2byte、2byte的不连续的空间,不能分配内存请求为6byte 的进程
内部碎片
:
进程所分配的内存可能比所需的要大,两个数字只差就是内部碎片。例如:有18464byte大小的孔,要分配内存请求为18462byte, 会剩下2byte 的孔
解决方法:紧缩
移动内存内容,把所有的空闲空间合并成一整块
注
:紧缩并非总是可能。只适用于动态重定位的时候;不适用于静态定位
四、分段
以用户视角去管理内存的方式,一个程序由多个逻辑段组成
一般组成:主程序、函数、方法、对象、堆、栈、局部变量、全局变量等
逻辑地址的定义:【分段号, 偏移】
需要段表, 段表条目包括:段基地址、段界限
五、分页
分页避免了外部碎片和紧缩
1.基本方法
实现分页的基本方法设计将物理内存
分为固定大小
的块,称为帧
或页帧
;而将逻辑内存
也分为同样大小
的块,称为页
或页面
。
一个页对应一个帧,当需要分配内存时,以页为单位分配内存。若程序大小为n 页,则需要有n 个帧来存放它,而这些帧是不必连续的内存空间
需要掌握空闲空间(空闲帧)信息,为了把逻辑地址转变为物理地址,还需要设置一个页表
(页表每个条目是跟页号所对应的帧号)
分页的硬件支持图
CPU生成的逻辑地址分为两个部分:页码
和页偏移
- 页号(页码)§: 是页表的索引,相应页表中存储着该页所在物理内存的基地址
- 页偏移(d): 偏移量,结合基地址形成物理地址
观察下图说明程序员的内存视图如何映射到物理内存。
可以看出,分页本身是一种动态定位。
采用分页方案不会产生外部碎片:每个空闲帧都可以分配给需要他的进程。但分页有内部碎片,因为进程所要求的内存并不一定是页的整数倍。
2.硬件支持
页表的硬件实现都有多种方法。
- 页表可以用一组专用寄存器来保存。但页表非常大时,就不可行了
- 将页表放入到内存中,并将页表基地址寄存器指向页表。
若把页表存入内存,会发生什么问题
?
为了访问数据,需要两次访问内存。第一次查页表,第二次访问地址。需要两次访问内存,这会导致数据访问速度慢
解决的办法
:采用高速硬件缓冲,转换表缓冲区(TLB)
TLB中只包含少数页表条目。当CPU产生一个逻辑地址后,把页码发送给TLB。如果找到这个页码,它的帧码也可以立即使用,访问内存;如果不在(未命中),那么就需访问页表。(下图页表应该在内存中)
3.保护
分页环境下的内存保护是通过每个帧关联的保护位
来实现的。
还有一位通常与页表中的每一条目相关联:有效-无效位
有效位
(v)表示相关的页在进程的逻辑地址空间内(合法)无效位
(i)表示相关的页不在进程的逻辑地址空间内(非法)
4.共享页
分页优点之一是可以共享公共代码
。进程的代码可分为可以共享的代码和不可共享的代码,可共享的代码通过共享页表的方式实现。
- 可共享的代码- 可重入代码(不能自我修改的代码:他在执行期间不会改变)
每个进程共享代码段的(页)逻辑地址相同 - 不可共享的代码- 私有代码和数据
针对私有代码和数据的(页)逻辑地址不同
六、页表结构
在把逻辑地址映射为物理地址的过程中,分页方式需要系统维护页表信息。
本节探讨组织页表的一些常用技术,分层分页
、哈希分页
、倒置分页
1.分层分页(层次页表)
把逻辑地址编址设为多层次,即多层次的页表。
p1用来访问外部页表的索引,p2是内部页表的页偏移
采用层次结构页表存储结构有什么优点?
- 可以实行页表的不连续存储
- 可以节约内存空间
那么问题来,为什么可以节约内存空间,进程要维护的页表大小是多少
?
假设一个系统具有32位逻辑地址空间和4K大小的页,每个页条目大小4byte。
那么,我们为覆盖4Gb的内存,每个进程要维持4Mb的页表
- 页表条目的数量 232/212=220
- 需要的页表大小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.倒置页表(反向页表)
为了减少页表消耗的内存空间而采用的方法
即,整个系统只有一个页表
,页表对于每个真正的内存页或帧才建立一个条目
反向页表编址:【进程标识符,页码,页偏移】
- 地址信息:需要用页码和页偏移来确定空间
- 进程信息:需要用进程标识符确定进程信息
参考
《操作系统概念》