操作系统-3.1内存管理概念
1. 原理
程序的链接&装入
将用户程序变为内存中可执行程序
编译
链接
- 静态链接:运行前链接成完整的装入模块
- 装入时动态链接
- 运行时动态链接:只在需要它时才进行链接
装入(逻辑地址→物理地址)
绝对装入:绝对地址
可重定位装入:
相对地址,从0开始
装入内存时进行重定位,若起始物理地址为100,所有地址+100
动态重定位
装入时并不会立即将逻辑地址→物理地址,等程序真正执行时才进行
进程的内存映像
当一个程序调入内存,就构成进程的内存映像
- 代码段:机器指令、只读数据
- 数据段:读/写数据
- 进程控制块PCB
- 堆:
- 存放动态分配的变量。
- 调用malloc动态向高地址分配空间
- 栈
- 实现函数调用
- 从用户空间最大地址→低地址增长
宏定义常量不专门分配空间,在预编译阶段直接读入

内存保护
①设上下限寄存器
②重定位寄存器+界地址寄存器
例:进程A物理地址100-279,逻辑地址0-179
- 重定位寄存器=100
- 界地址寄存器=179
- 此时访问逻辑地址80的内存单元
- 80<179→未越界(否则抛出异常)
- 80+100=180→访问物理地址180内存单元
2.连续分配
单一连续分配
内存(低→高):系统区、用户区
- 只有一道用户程序
- 无外部碎片
固定分区分配
用户区划分成若干固定大小分区
动态分区分配
不会预先划分,在进程装入时根据进程大小动态建立分区
- 无内部碎片,有外部碎片(可采用“紧凑技术”解决)
动态分区分配算法
①首次适应(⭐综合性能最好)
从低地址开始找,找到第一个能够满足大小的空闲分区
②最佳适应
优先使用更小的空闲区(但会有很多外部碎片)
③最坏适应
优先使用更大的空闲区 (这样分完剩下的那块仍然会比较大,也许以后还能用。但如果之后有大进程可能无处放)
④临近适应
从上次查找结束的地方开始查找,仍然按顺序排列
3.分页
- 将内存分为一个个大小相等的分区——“页框”
页框=页帧=内存块=物理块=物理页面
将进程逻辑地址也分为和页框大小相等的“页”
页表:
- 一个进程对应一张页表,存放在PCB中
- 记录页面和实际存放的页框之间的映射关系
内存块号→物理地址;页号→逻辑地址
⭐
基本地址变换机构
[例题]

具有快表的地址变换机构
什么是快表
TLB,不是内存,是访问速度>>内存的高速缓存
内存中的表称为慢表
变换过程
- CPU给出逻辑地址,由硬件转换,比较快表中所有页号
- 匹配→直接取出对应页框号(一次访存即实现存取数据)
- 未匹配→访问主存页表,同时存入快表(如果满了就删一个旧页表)
两级页表
在系统中增设外层页表寄存器——存放页目录始值
①逻辑地址的页目录号→页目录索引→对应页表初始值
②二级页号→页表分页的索引→对应页表项
③页表项中 物理块号+页内偏移 拼接→物理地址→访问内存单元
4.分段
将进程按照自身逻辑关系划分为若干段
分段系统逻辑地址=段号+段内地址
段表
每个进程有一个段表(每一行:段号+⭐段长+基址)

- 需要检查段号是否越界、段内地址是否超过段长(和分页地址变换的最大区别)
分页vs.分段
①
- 页是物理单位。用户不可见
- 段是逻辑单位。用户可见
②
- 页大小固定
- 段大小不固定
③
- 分页的用户进程地址空间是一维(直接给一个数,即逻辑地址)
- 分段的用户进程地址空间是二维(段号、段内地址两个数)
5.段页式
逻辑地址结构
段号+页号+页内偏移量
- 二维:用户只给出段号+段内地址,“分页”对用户不可见
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 BaBaLiBoo!


