操作系统入门 – 内存管理
1.内存种类
1.1 虚拟内存(VIRT)
- 进程需要的虚拟内存大小,包括进程使用的库、代码、数据以及malloc、new分配的堆空间和栈空间等。
- 若进程申请了10MB内存但实际使用了1MB,则物理空间会增长10MB。
1.2 常驻内存(RES)
- 进程当前使用的内存大小,包括使用中的malloc、new分配的堆空间和栈空间,不包括sawp out量。其中还包含其他进程的共享。
- 若申请10MB则实际使用1MB
1.3 共享内存(SHR)
- 除了自身进程的共享内存,也包括其他进程的共享内存。
- 进程只使用了几个共享库的函数,但包含了整个共享库大小。
- 计算某个进程所占物理内存大小为RES - SHR.
- swap后会降下来。
2.操作系统内存管理
2.1 内存管理的意义
目前计算机硬件发展很快,内存容量也越来越大。但是仍然不可能将所有用户进程和系统所需要的全部程序和数据放入主存中,所以操作系统必须将内存空间进行合理地划分和有效地动态分配。操作系统对内存的划分和动态分配,就是内存管理的概念。
2.2 内存管理的内容
操作系统中内存管理主要负责内存分配与回收(malloc:申请内存 , free:释放内存),同时将逻辑地址映射到物理空间也是内存管理的内容。其中主要有以下四个功能:
- 内存空间分配与回收:由操作系统完成主存储器空间的分配和管理,使程序员摆脱存储分配的麻烦,提高编程效率。
- 地址转换:在多道程序环境下,程序中的逻辑地址与内存中的物理地址不可能一致,因此存储管理必须提供地址变换功能,把逻辑地址转换成相应的物理地址。
- 内存空间扩充:利用虚拟存储技术或自动覆盖技术,从逻辑上扩充内存。
- 存储保护:保证各道作业在各自的存储空间内运行,.互不干扰。
2.3 内存管理目的
提高内存利用率。所谓提高利用率就是尽可能让更多进程沾满内存。进程在内存中的分布又可以分为连续和非连续。
2.4 程序装入与链接
2.4.1 程序装入过程
创建进程首先要将程序和数据装入内存。将用户源程序变为能在内存中执行的程序需要以下步骤:
- 编译:由编译程序将用户源代码编译为若干个 目标模块。
- 链接:由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的 装入模块。
- 装入:由装入程序将模块装入内存运行。
2.4.2 程序链接
- 静态链接:在程序运行之前,先将各个目标模块及所需函数库链接成一个完整的可执行程序,以后不再拆开。
- 装入时动态链接:将用户源程序编译后所得到的一组目标模块,在装入内存时,采用变装入边链接的方式。
- 运行时动态链接:对某些目标模块的连接,是在程序执行中需要该目标模块时,才对其进行链接。优点在于便于修改和更新,便于实现对目标模块的共享。
2.5 地址映射
程序在编译后,每个目标模块都是从0号单元开始编址,称为该目标模块的相对地址(逻辑地址)。当链接程序将各个模块链接为一个完整可执行的目标程序时,链接程序顺序依次按各个模块的相对地址构成统一的从0号单元开始编址的逻辑地址空间。简单来说就是该条链接是从0号开始顺序往下编址。
物理地址空间是指内存中物理单元的集合,它是地址转换后的最终结果。进程在运行时执行指令和访问数据最后都需要通过物理地址从主存中存取。当装入程序将可执行代码装入内存中时,必须通过地址转换将逻辑地址转换为物理地址。
2.5 内存保护
内存在分配前,需要保护操作系统进程不受影响,同时保护用户进程不受其他用户进程影响。采用重定位寄存器和界地址寄存器来实现这种保护。重定位寄存器含有最小的物理地址值,界地址寄存器含逻辑地址值。每个逻辑地址值必须小于界地址寄存器。内存管理机构动态地将逻辑地址与界地址寄存器比较,若未发生越界,则加上重定位寄存器的值后映射为物理地址,最后送交内存单元。
3.内存覆盖与交换
3.1 内存覆盖
3.1.1 问题产生
早期计算机内存空间较小,且其中需要存放一道用户程序,但由于内存空间有时连用户进程都放不下,因此采用覆盖来解决。
3.1.2 实现过程
程序运行时不是任何时候都要访问程序和数据的各个部分,因此可以把用户空间分为一个固定区域和若干覆盖区域。将经常活跃的部分放在固定区,其余部分按调用关系分段。首先把将要方位的段放入覆盖区,其余部分放入外存,在需要调用前载入覆盖区替换原来的数据。
3.2 内存交换
3.2.1 实现过程
交换是把等待状态下的进程从内存中换出至外存,腾出内存空间,把就绪的进程从外存换入内存中准备执行。
3.2.2 注意事项
- 交换需要备份存储,需要磁盘空间足够大,并提供对内存映像的直接访问。
- 为有效使用CPU,需要每个进程的执行时间比较长,影响交换时间的是转移时间。转移时间与所交换的内存空间成正比
- 换出进程必须确保该进程完全处于空闲状态。
- 交换的空间通常为磁盘上一整块区域,且独立于文件系统。
- 内存交换一般发生于内存空间不足的时候,当内存负荷降低后暂停。
3.3 总结
交换主要是不同进程之间,而覆盖则是在同一程序或进程中。目前操作系统主流采用内存交换技术。
4.内存分配
4.1 内存连续分配
连续分配方式,是指为一个用户程序分配一个连续的内存空间。它主要包括单一连续分配、固定分区分配和动态分区分配。
4.1.1 单一连续分配
内存在该分配模式下分为系统区和用户区,系统区为操作系统提供使用,通常为低地址部分、用户区为除系统区外的内存空间。
- 优点:简单、无外部碎片、可以采用覆盖技术,无需额外技术支持。
- 缺点:只能用于单用户、单任务的操作系统,内部有碎片,存储利用率低。
4.1.2 固定分区分配
固定分区分配是最简单的一种多道程序存储管理方式,它将用户内存空间划分为若干个固定大小的区域,每个分区只装入一道作业。当存在空闲分区时,便可以再从外存的后备作业队列中选择适当大小的作业装入该分区。
- 分区方式
- 分区大小相等:用于一台计算机控制多个相同对象的场合,缺乏灵活性。
- 分区大小不等:划分为含多个较小的分区、适量的中等分区及少量大分区
但这种存储方式存在以下问题: - 程序可能太大而无法放进任一分区,此时只能使用覆盖技术
- 主存利用率低,当程序体积小于固定分区大小时,放进去也需要占用这一分区,造成浪费。
4.1.3 动态分区分配
动态分区分配不会先划分内存,而是在进程装入内存时动态分配空间,分区大小和数量是可变的。动态分区刚开始没有什么问题但之后会出现许多小内存块,随着内存块增多,利用率下降。
如果内存空间足够大,则操作系统必须明确分配哪个内存给进程使用,即动态分区分配策略,其算法如下:
- 首次适应算法:空闲分区以地址递增的次序链接。分配内存时顺序查找,找到第一个能满足大小的分区。
- 最佳适应算法:空闲分区安容量递增形成分区链。找到第一个能满足大小的分区。
- 最坏适应算法:空闲分区按容量递减次序链接。找到第一个能满足要求的空闲分区。
- 邻近适应算法:由首次适应算法演变。不同之处是分配内存时从上次查找结束的位置开始继续查找。
4.2 内存非连续分配
非连续分配允许一个程序分散地装入不相邻的内存分区中,根据分区的大小是否固定分为分页存储管理方式和分段存储管理方式。
4.2.1 基本分页存储管理方式
分页是将主存空间划分为大小相等且固定的块,块相对较小,作为主存的基本单位。每个进程也以块为单位进行划分,进程在执行时,以块为单位逐个申请主存中的块空间。分页本身不会产生外部碎片,但是块的大小相对分区要小很多,且进程也按照块进行划分,进程运行按块申请内存。因此进程只会在为最后一个不完整的块申请一个主存储块时才会产生碎片。
4.2.2 分页存储的基本概念
- 页面和页面大小:进程中的块称为页,内存中的块称为页框。外存也以同样方式划分,称为块。进程执行时申请内存空间,即为每个页面分配页框。
- 页面大小:为方便地址转换,页面大小应是2的整数幂。页面大小适中,若页面过小则进程页面数过多,页表会过长,占用大量内存。页面过大则页内碎片增多,降低利用率。
- 地址结构:由两部分组成,前一部分为页号P,后一部分为页内偏移量W,地址长度为32 位,其中011位为页内地址,即每页大小为4KB;1231位为页号,地址空间最多允许有220页。
- 页表:为了便于在内存中找到进程的每个页面所对应的物理块,系统为每个进程建立一张页表,记录页面在内存中对应的物理块号,页表一般存放在内存中。
4.2.3 基本地址变换机构
地址变换机构的任务是将逻辑地址转为内存中的物理地址,该机构通过页表实现。
4.2.4 基于快表的地址变换机构
若页表全部放在内存中,则存取一个数据或一条指令至少要访问两次内存,因此在地址变换机构中增加一个高速缓冲器即快表来存放当前访问的若干页表项,以加速地址变换的过程。
4.2.4 多级页表
于引入了分页管理,进程在执行时不需要将所有页调入内存页框中,而只要将保存有映射关系的页表调入内存中即可。但是我们仍然需要考虑页表的大小。
以32 位逻辑地址空间、页面大小4KB、页表项大小4B为例,若要实现进程对全部逻辑地址空间的映射,则每个进程需要220,约100万个页表项。也就是说,每个进程仅页表这一项就需要4MB主存空间,这显然是不切实际的。而即便不考虑对全部逻辑地址空间进行映射的情况,一个逻辑地址空间稍大的进程,其页表大小也可能是过大的。
5.总结
从内存种类再到内存的管理方式,本文并未深入介绍,只是了解了基本的工作原理,未来将持续更新。