物理内存
物理内存,取决于寻址空间和实际内存条的大小
- 8086只有20根地址线,它的寻址空间是0-2^20,只有1M,插上128MB的内存条它的物理内存也只是1M
- 32位机器的寻址空间是0-2^32,最大支持4GB内存,而插上2GB的内存条则物理内存为2G
直接使用物理内存的弊端
进程空间不隔离,没有权限保护
因为程序都是直接访问物理内存,所以一个进程可以修改其他进程的内存数据,甚至可以修改内核地址空间中的数据
程序运行时候的地址不确定
一个程序想要访问自己程序内存的址0x00000000地址,但是在物理内存上分配内存是随机的,所以访问0x00000000可能不是自己的内存区域
内存利用率低
假设内存是连续分配的(也就是程序在物理内存上是连续的)
1.进程A进来,向os申请了200的内存空间,于是os把0~199分配给A
2.进程B进来,向os申请了5的内存空间,os把200~204分配给它
3.进程C进来,向os申请了100的内存空间,os把205~304分配给它
4.这个时候进程B运行完了,把200~204还给os
但是很长时间以后,只要系统中的出现的进程的大小>5的话,200-204这段空间都不会被分配出去(只要A和C不退出)。过了一段更长的时间,内存中就会出现许许多多200-204这样不能被利用的碎片
虚拟地址空间
为了解决直接操作物理内存带来的问题,所以引入了虚拟地址空间,因为这个空间是虚拟的,所以可以无限大。
每个进程都可以有自己的虚拟地址空间
基本内存管理(分段)
在虚拟地址空间和物理地址空间之间做一一映射,这里映射的是一片连续的物理内存
- 虚拟内存解决了运行时内存地址不确定的问题
- 分段解决了内存空间的隔离,因为程序操作的是虚拟内存,而分段使得对应的物理内存不会重叠
- 因为分段映射的是一段连续的物理内存,所以没有解决内存利用率低的问题
实现分段的策略
固定分区
将内存分为几个固定的区域,每个区域的大小固定(通常不同),需要加载程序是选择一个闲置且容量足够大的分区进行加载
上面共享队列的固定分区策略可能造成一个小程序占用一个大分区的情况,从而造成内存里虽然有小分区闲置但无法加载大程序的情况。可以采用多个队列,给每个分区一个队列,程序按照大小排在相应的队列里,如下图所示,这时一种分开队列的固定分区
这种方式也有缺点:如果还有空闲分区,但等待的程序不在该分区的等待队列上,就将造成有空间而不能运行程序的情况
非固定分区
非固定分区的思想在于除了划分给OS的空间之外,其余的内存空间是作为一个整体存在的。当一个程序需要占用内存空间时,就在该片空间里面分出一个大小刚刚满足程序所需的空间。再来一个程序时,则在剩下的空间里再这样分出一块来。在这种模式下,一个程序可以加载到任何地方,也可以和物理内存一样大。
- 程序运行时的内存空间会增长,需要预留出增长空间
- 预留太多会造成浪费,太小可能造成程序无法运行或者发生分区交换
交换分区swap
因为系统分配给程序的空间分段映射的是一段连续的物理内存,所以空间不够时可以将程序倒到外置存储中,再寻找足够的内存空间加载
- 因为每次空出来的内存空间都是相对比较小的,所以多次交换之后内存碎片会越来越多
- 交换过程涉及到外置存储,速度比内存低很多
- 单一程序不能超过物理内存空间
双基址
要运行两个相同的程序,只是数据不一样,那么我们可不可以进行指令的共享?可以!那么我们怎么使在共享的过程中不产生错误呢?那就是双基址:给指令和数据各自配置基址。
其实就是将指令和数据分成不同的段
分页
因为分段技术映射到物理内存上是一段连续的空间,所以无可避免的会造成内存利用率不高的问题
为了增加内存的利用率,需要使用分页技术
什么是分页
将虚拟内存空间和物理内存空间皆划分为大小相同的页面,如4KB、8KB或16KB等,并以页面作为内存空间的最小分配单位,一个程序的一个页面可以存放在任意一个物理页面里。
虚拟地址的构成与地址翻译
在分页系统中,一个程序的虚拟地址由页面号和页内偏移值两部分组成
32位寻址系统中,如果页面大小为4k,则页面号占20位,页内偏移值占12位
虚拟内存页到物理内存页的映射由内存管理单元完成(MMU)
页表的根本功能是提供从虚拟页面到物理页面的映射。因此,页表的记录条数与虚拟页面数相同。此外,内存管理单元依赖于页表来进行一切与页面有关的管理活动,这些活动包括判断某一页面号是否在内存里,页面是否受到保护,页面是否非法空间等等,页表是一个硬件数据结构
分页系统的优点
- 分页的大小比较小,不会产生外部碎片
- 一个进程占用的内存空间可以不是连续的,并且一个进程的虚拟页面在不需要的时候可以放在磁盘中
分页系统的缺点
- 页表大小很大
- 32位寻址4k大小的页的页表大小为2^20(页数)*4Byte(表项长度=20位页号+12位控制位)=4MB
- 分页系统存在的一个无法容忍,同时也是分页系统无法解决的一个缺点就是:一个进程只能占有一个虚拟地址空间。在此种限制下,一个程序的大小至多只能和虚拟空间一样大,其所有内容都必须从这个共同的虚拟空间内分配。
逻辑分段
逻辑分段将一个程序按逻辑关系分解为多个段
- 每个逻辑单元可单独占用一个虚拟地址空间,这样使得编写程序的空间大为增长。
- 由于段式按逻辑关系划分,因此共享起来十分方便。
- 对于空间稀疏的程序来说,分段管理将节省大量的空间。
重叠overlay
如果一个程序需要使用比物理内存更大的内存空间怎么办?
此时,可以将程序按照功能分成一段一段功能相对完整的单元,一个单元执行完成后再执行下一个单元,这就是重叠(overlay)
相当于一列火车从上海到北京,不需要一整段完整的铁轨,只需要两段火车长度的铁轨,不断移动铁轨,就可以让火车一直往前开
段页式
综合了逻辑分段和分页的优点,将程序分为多个逻辑段,在每个段里面又进行分页,即将分段和分页组合起来使用。
采用多级页表,顶级为段表,次级为页表。由段号在段表里面获得所应该使用的页表,然后在该页表里面查找物理页面号
参考资料
操作系统核心原理-5.内存管理(上):基本内存管理
操作系统核心原理-5.内存管理(中):分页内存管理
操作系统核心原理-5.内存管理(下):段式内存管理
基本内存管理的简单介绍