使用内存:将程序放到内存中,PC指向开始地址
放入内存后会发现地址上会出现问题,如下
要调用地址为40处的指令,但其实要调用的指令在内存中是1040,你却跑到40处了,显然错了,所以要修改程序的地址
但是我们发现程序载入后还需要移动,如下:
我们会把睡眠中的进程1移到磁盘,把要运行的进程2调入内存,当进程1要运行时再调回内存,那么问题来了,假设开始时的进程1的起始地址1000,那么调出去再调回来后1000那个地方可能已经不空闲了
所以会用到下面的重定位方法:
分段
[DS:100]指的是360k+100
CS,100 指的是180k+100
每个PCB里都有LDT,把段号和段号的地址就记录在LDT,LDT就是映射表
分区
分区就是内存分割成一块一块的区域,这样就可以将程序的各个段载入到相应的内存分区
固定分区与可变分区
- 固定分区
等分,操作系统初始化时将内存等分成多个分区 - 可变分区
因为段的请求有大有小,都分配同样大小的内存区显然不合适,所以分区有大有小才合适
- 可变分区的管理过程
举例:
现在的内存分配情况如下:
现在有一个段提出请求分配100k的内存
分配后的情况如下:
现在假设段2不再需要了,此时需要释放内存
释放后的情况如下:
再次申请,又有一个段提出请求40k的内存
此时有两个空闲区,50k的和150k的,那么选哪个比较好呢?有三种方法:
首写适配:检索简单,复杂度为O(1)
最佳适配:会分割出很多比较碎的分区
最大适配:分区比较均匀
可变分区造成的问题:同样举例
内存碎片:因为不停的请求释放,会造成很多内存碎片
假设把刚刚的请求40k换成160k,此时的两个空闲区,50k的和150k的都放不下,怎么办呢?
内存紧缩的时候,上层的用户进程就必须停下来,不能执行,所以可能等待时间太久,用户体验极差,所以需要引入分页
分页
如下图,将内存分成一页一页的,一页占4k
操作系统初始化时将内存分好页
针对每个段内存请求,系统一页一页的分配给这个段
内存分页不再需要内存紧缩,一个段最大也就浪费4k,浪费的少
页载入内存后:
上图中的示例将2240右移3位得出逻辑地址结果
为了提高内存空间利用率,页应该小,但是页小了页表就大了
2^32=4G/4k=1M=2 ^20k
这里就引出了多级页表
多级页表
快表
段页结合的实际内存管理
程序员希望用段,物理内存希望用页,所以使用段页结合
对用户透明是指用户感觉不到
一个实际的段页式内存管理