- 程序装入与链接
- 程序包括代码、数据和堆栈三个部分。
- 逻辑地址和物理地址空间
- 物理地址空间:硬件支持的地址空间
- 逻辑地址空间:CPU运行时,进程看到的进程空间
- 逻辑地址的生成:高级语言源码 --编译--> 指令汇编码 --编译--> 二进制代码 --链接:函数库平移--> 调用函数库(如果需要调用别的内存地址的函数)
- 程序加载重定位(逻辑地址平移):内存实际分配位置不一定从0开始
- 编译时:假设起始地址已知,如果起始地址改变必须重新编译
- 加载时:如编译起始位置未知,编译器需要生成可重新定位的代码,加载时需要生成绝对地址
- 执行时:执行代码可移动,需要地址转换(映射的支持)
- 内存保护
给进程分配一块不小于指定大小的连续的物理内存区域(代码数据堆栈)
- 内存碎片:无法利用的空闲内存
- 外部碎片:两个区域之间的未被使用区域
- 内部碎片:分配单元内部的未被使用内存,取决于分配单元大小是否需要取整
- 动态分区分配:(指定大小、可变、地址连续)
- 操作系统维护数据结构:所有进程已分配分区和空闲分区
- 策略:最先匹配,最佳匹配,最差匹配
- 连续分配的缺点:
- 分配给程序的物理内存必须连续,存在外碎片和内碎片,内存分配的动态修改麻烦,内存利用率较低
- 非连续分配的目标:
- 提高内存使用率,提高管理灵活性 => (允许进程使用非连续物理内存,允许共享代码和数据,支持动态加载和动态链接)
- 管理方式:
- 分页管理方式:
- 特点:页比较小(2的指数幂),会出现内存访问性能问题(访问一个内存单元需要两次内存访问:获取页表项+访问数据)
- 缺陷:页表可能非常的大
- 补偿:使用快表缓存,间接访问(多级页表,将忽略大部分没有被使用到的页表)
- 分段管理方式:
- 特点:进程的段地址由多个地址空间组成,包括:主代码段、子模板代码段、公用库代码段、堆栈段、堆数据、初始化数据段、符号表等。
- 逻辑地址空间连续但物理地址空间不一定连续
- 段表示访问方式和存储数据等属性相同的一段地址空间,对应一个连续的内存"块"
- 段访问的硬件实现:段号(通过查询段表来获取基址和长度等相关信息)+段内偏移(更加具体的偏移定位)
- 段表是限制其发展的大一阻碍(段表占用空间较大,需要将其放到一页中)
- 段页式管理方式
- 分页和分段管理的组合
- 分页管理方式:
满足大容量和高速之间的矛盾
- 覆盖技术:在较小的可用内存中运行较大的程序
- 方法:依据程序的逻辑结构,将程序划分为多个独立模块;将不会同时执行的模块共享一块内存区域。(拓扑排序)
- 必要部分:常用的功能、代码和数据常驻内存
- 可选部分:不常用的功能放在其他程序模块,只在需要的时候装载到内存
- 交换技术:增加正在运行或者需要运行的程序的内存
- 方法:暂时将不在运行状态的进程放到外存中(磁盘)
- 换入换出的基本单位:整个进程的地址空间
- 换出:将一个进程的地址空间存入外存
- 换入:将一个进程的地址空间载入内存
- 最佳置换算法(OPT)
- 先进先出置换算法(FIFO)
- 最近最少使用置换算法(LRU)