0.如何分配物理内存
内存分成两部分:内核使用部分、用户使用部分,那么它们是否是平等的呢?
不平等,试想如果是平等的:那么我们可以随意修改内核所用的内存,那么系统岂不是乱套啦!
既然不平等,就要引入保护机制,防止恶意修改。
我们如何记录哪些内存已经分配/未分配呢?这些信息保存在哪里?
有以下几种物理内存分配方案:
- 分区存储管理
- 分页存储管理
- 多级页表管理
- 虚拟存储管理
- 分段存储管理
1. 连续内存分配
1.1 计算机体系结构和内存分层体系
基本硬件结构:
CPU(程序执行处),内存(放置了代码和处理的数据),设备(I/O)
操作系统对内存分配做了什么
(1)抽象,逻辑地址空间;
(2)保护,独立地址空间;
(3)共享,访问相同内存;
(4)虚拟化,更多的地址空间,对应用程序透明
操作系统采用的内存管理方式
- 重定位:段地址+偏移
- 分段:分成代码、数据、堆栈
- 分页:把内存分成最基本的单位
- 虚拟存储:把数据存到硬盘上,使得逻辑地址空间大于物理内存空间
1.2 地址空间和地址生成
物理地址空间:硬件支持的地址空间
逻辑地址空间:一个运行的程序所看到的内存空间
两者之间存在映射关系,最终执行时还是落在物理地址空间上。
源程序不能再计算机上直接被运行,需要通过三个阶段的处理:编译程序处理源程序并生成目标代码,链接程序把他们链接为一个可重定位代码,此时该程序处于逻辑地址空间中;下一步装载程序将可执行代码装入物理地址空间,直到此时程序才能运行。
可执行程序逻辑地址转换为物理地址的过程被称为 “地址重定位”。
逻辑地址是如何映射到物理地址:
CPU方面
1.运算器ALU需要在逻辑地址的内存内容(CPU要逻辑地址)
2.内存管理单元MMU寻找在逻辑地址和物理地址之间的映射(然后MMU找逻辑和物理地址的关系)
3.控制器从总线发送在物理地址的内存内容的请求(关系找到后,去找对应物理地址)
内存方面
4.内存发送物理地址内存内容给CPU(物理地址找到了,给CPU)
操作系统方面
5.建立逻辑地址和物理地址之间的映射(确保程序不相互干扰)
1.3 内存碎片和分区的动态分配
内存碎片问题
内存碎片:两个进程之间连续物理内存地址空间未使用的内存为内存碎片
外部碎片:在分配单元之间的未使用内存
内部碎片:在分配单元内部未使用的内存
分区分配
连续内存分配有两种实现方式:固定分区分配,动态分区分配
动态分区分配
- 动态分配下,按照作业大小来划分分区,但划分的时间、大小、位置都是动态的。系统把作业装入内存时,根据其所需要的内存容量查看是否有足够空间,若有则按需分割一个分区分配给此作业;若无则令此作业等待内存资源。
- 操作系统需要维护的数据结构:所有进程的已分配区以及空闲分区
- 动态内存分配策略:
最先匹配(地址优先):从0地址往后查找和使用第一个可用空闲快
最佳匹配(空闲分区大小优先):找比需求大但最接近需求的空闲内存块,产生尽可能小的内存碎片。
最差匹配(最大空闲分区优先):使用最大的空闲块。
1.4 碎片整理
碎片整理:通过调整进程占用的分区位置来减少或避免分区碎片。
压缩式碎片整理
使用条件:所有的应用程序可以动态重定向。
调整内存中程序运行的位置,通过拷贝尽量把程序放到一起,空出较多的空闲位置。
交换式碎片整理
外存(swap分区)当做内存的备份,把在等待的进程包括数据放在外存上,腾出空间给其余运行的进程(抢占等待进程,回收其内存),这个方法也要考虑开销和换哪个进程。
2. 非连续内存分配
2.1 需求背景
- 连续分配物理地址必须连续,存在碎片,动态修改困难,导致内存利用率极低。
- 非连续内存分配可提高内存利用效率和管理灵活性。
- 允许一个程序使用非连续的物理地址空间。
- 允许共享代码和数据
- 支持动态加载(进程在内存中大小是动态)和动态链接
非连续内存空间的分配要解决的问题
- 如何实现虚拟地址和物理地址的转换
- 软件实现(灵活,开销大)
- 硬件实现(够用,开销小)
- 如何选择非连续分配中的内存分块大小
- 段式存储管理(segmentation)
- 页式存储管理(paging)
2.2 段式存储管理
把逻辑地址空间分散到多个物理地址空间,堆→堆,运行栈→运行栈,程序数据→数据,运行exe→代码和库
逻辑地址空间是连续的,物理地址是离散的,每个段的逻辑地址都由段号s和段内偏移addr构成。
段内要求连续,段间不一定连续,故整个进程的地址空间是二维的。
访问机制
首先用段号查段表,里面有它的起始地址和长度,由操作系统控制。
MMU检查addr偏移是否大于段的长度,合法就用段基址+偏移得到实际的物理地址
2.3 页式存储管理
分页也是实现机制和寻址,也需要页号和偏移,区别在于页帧的size不变。
- 页帧
- 把物理地址空间划分为大小相同的基本分配单位,是2^n;
- 二元组(帧号,帧内偏移)
- 页面
- 把逻辑地址空间划分为相同大小的基本分配单位
- 页面的大小和页帧必须是相同的。
- 二元组(页号, 页内偏移)
- 页面到页帧的转换关系
- 实际上就是逻辑地址到物理地址的转换
- 页表 每个进程都有一个页表&#x