操作系统内存管理——连续内存分配
什么是内存管理
前面我们已经详细学习了操作系统的进程调度模块,其中多次提到了进程的内存抽象,不妨来回顾一下。如图所示,我们把进程的内存抽象表示为下面的结构:
- stack存放程序的局部变量
- heap可以用来动态申请空间
- data存放全局变量、静态变量
- text存放代码
那么,这个内存抽象该如何提供呢?需要哪些物理硬件?如下所示。
要知道,CPU 只能访问物理内存。如果物理内存不够,那么可以借助磁盘来提供存储空间。
那么,当有一个物理内存和一块磁盘来为多个进程提供内存抽象时,该怎么让它们正常运行呢? 其实,这就是操作系统内存管理模块所做的任务。
物理内存分配
尝试回答下面的问题。
Question1:能不能把所有的内存都分配给用户呢?
Answer1:显然不能,我们必须给操作系统预留一部分内存,其余的部分可以分配给用户。
Question2:既然我们把内存分成给用户的部分、给操作系统的部分,那这两部分是否平等呢?
Answer2:显然不是平等的,如果任何用户都可以修改内核的内存,系统还怎么正常运行呢?所以用户进程不可以访问操作系统的内存。
同时我们要提供一定的保护机制,比如分配给一个用户进程的内存,不可以被其他的进程读取或修改,除非向操作系统请求。
有了以上的构想,我们要设计一个内存管理模块,还需要解决下面问题:
Question3:如何记录哪些内存已分配/未分配?这些信息存在哪里?
Question3.1 && 3.2:上面这个问题衍生出的问题是,新的请求到达时,如何分配内存给它?进程消亡时又该如何收回内存?
Question4:如何把程序的逻辑地址转换成实际存储的物理地址?
物理内存分配方案
物理内存分配方案主要有以下几种,后面会依次讲解每一种分配方案。
- 连续分配存储管理
- 分页存储管理
- 虚拟存储管理
- 分段存储管理
1. 连续分配存储管理
1.1 单一连续分配
我们能想到最直接和最简单的分配方式,是单一连续分配。
方法:
- 在这种分配方式中,我们把内存分成了系统区和用户区,用户区的全部内存分配给进程使用。
- 我们不需要进行地址转换,程序生成时使用的是绝对地址,它的逻辑地址就等于物理地址。
- 然而,用户区内存全部分配给了进程,所以这种分配方式只适用于单用户、单任务的操作系统。
- 在单用户的环境下,机器由用户独占,如果有其他任务想要运行,必须等待正在运行的任务运行结束或强行终止。
- 同时,在这种分配方式中,如果没有提供保护机制,用户进程是可以修改系统内存的,如MS-DOS。
优点:
- 简单
- 基本不需要硬件支持
缺点:
- 只适用于单用户、单任务环境
1.2 固定分区分配
为了克服单一连续分配的缺陷,解决它只适用于单用户单任务的情形,我们引入了固定分区分配。
方法:
- 在固定分区分配中,我们把内存分成了若干个大小相等或不等的分区,每个区域可以装入一道程序,只要分区的大小大于等于进程的大小即可。
- 在固定分区分配方案中,逻辑地址和物理地址不再相等,它们之间的转换过程如下图所示。对于当前进程,CPU检查它的