存储器管理
连续分区两种方式对比
固定分区 | 可变分区 | |
---|---|---|
分区内存大小 | 固定 | 可变 |
内存利用率 | 低 | 提高 |
内碎片 | 存在 | 不存在 |
外碎片 | 不存在 | 存在 |
碎片解决方案 | 无 | 紧缩技术 |
并发程序个数 | 固定 | 可变 |
内存管理数据结构 | 内存分配表 | 分区链表 |
内存分配策略 | 最先/最佳匹配法 | 最先/最佳/最坏/下次匹配法 |
内存回收策略 | 分区状态 占用 => 空闲 | 更新分区链表 |
内存保护策略 | 限长寄存器 | 限长寄存器 |
内碎片:进程所占用的分区内部未被利用的空间
外碎片:各进程之间难以被利用的空闲区间
不变分区两种策略
单个输入队列的
最先匹配法 | 最佳匹配法 | |
---|---|---|
解释 | 找第一个可以装入该分区的 | 搜索整个队列,选择能装入的该分区的最大进程 |
优/缺点 | 小进程可能浪费大的空间 | 减少空间的浪费 |
可变分区四种策略
最先 | 最坏 | 最佳 | 下次 | |
---|---|---|---|---|
解释 | 找第一个 | 找最大的 | 找大小最为接近,使得外碎片最小 | 从上次找的地方再找找不到循环到前面去 |
优点 | 速度很快,高地址较大分区易于保留 | 不留下小的空闲分区 | 速度快,分布均匀 | |
缺点 | 大分区没有保留下来 | 外碎片浪费 | 大分区不易保留 |
理解重定位
物理地址:内存地址,绝对地址,实地址
逻辑地址:相对地址,虚地址
地址映射 (地址重定位) :逻辑地址 ->物理地址
静态重定位 | 动态重定位 | |
---|---|---|
区别 | 载入内存的时候指令地址固定 | 运行的时候指令地址固定 |
移动 | 此段程序载入内存后不可以移动 | 此段程序载入内存后可以移动 |
需求 | 不需要寄存器 | 需要基址寄存器 |
段页存储对比
页式存储 | 段式存储 | |
---|---|---|
数据结构 | 页表 & 物理页面表 | 段表 |
表 | 逻辑页号 & 内存块号(物理页面号) | 段号 & 段起始地址 & 段长& 保护位 |
优点 | 没有外碎片,内碎片也很小 | 分为多个模块,实现每个模块分别编写,编译,保护,段单位共享 |
程序不必连续存放 | 程序不必连续存放 | |
缺点 | 程序必须全部装入内存 | 程序必须全部装入内存 |
维护页表也是一笔开销 | 存在外碎片 |
1. 页存储理解
因为是动态重定位:所以给出的是逻辑地址 高位变成逻辑页面号(数组下标) 低位则为页内偏移
理解为什么可以转换:
程序以动态重定位方式进行,假如给的是8位逻辑地址,假如内存被分为16字节一个块,一共16个页
从 0000 | 0000 到 1111|1111
0000 | 0000 第零页的开始
0000 | 0011 第零页的0011偏移量
0000 | 1111 第零页的最后一块 下一个内容就要翻一页了
0001 | 0000 第一页开始 同理
0001 | 1111 需要翻页了
0002 | 0000 就是第二页
假如给出的逻辑地址 0001 | 1111 现在知道页数了
那么要找到物理块号 我们还有两个问题
1.他是谁的第一页?
2.页表放在哪里?
但一个进程建立都给出了页表,那么当这个进程运行的时候,他会把他的页表的起始地址放在基址寄存器中,所以 第二个问题就解决了,第一个问题当然也解决了,你需要访问的是在占用CPU的,这时候你寄存器里存的页表起始地址就是他的第一页,最后一个问题?
他是表里面的哪一个?因为这样才能找到块号
页表起始地址+页号(右偏移四位)或 页表起始地址+页面大小*页号
式子就是他 ,找到相应块号,然后转换成物理地址 假如块号就是3 然后毕竟是 0011|1111
这样完成了逻辑地址到物理地址转换
这样的坏处
两次访问内存,CPU访问内存相当慢
解决方案
于是有了TLB 存放最近一段时间最常用的页表项, 逻辑页面号与 物理页面号直接对应
2. 段存储的理解
段存储给出逻辑地址的本身就二维地址
同样知道 假如给的是0001 | 1111 第一维段号 第二维段内偏移 同样知道第一段
两个问题?
1.他是谁的第一段?
2.段表放在哪里?
但一个进程建立都给出了段表,那么当这个进程运行的时候,他会把他的段表的起始地址放在基址寄存器中 还有个问题
他是表里面的哪一个?
段表起始地址+段号(右偏移四位)
找到段的起始地址 多出来的操作就是 偏移量与得到段长比 是否越界!
段起始地址+偏移地址 就是物理地址
是不是两者很像 主要是因为逻辑地址含义不一样而已
段还有一种 ,学过8086处理器的知道
是直接在CS ,DS,SS,ES给出段起始地址 的