操作系统总结(一)——虚拟内存

1.操作系统内存管理(虚拟内存)

1.1 虚拟内存的概念

操作系统为每个进程分配独立的一套虚拟地址,这就是虚拟内存。虚拟内存是一个抽象概念,它为每个进程提供了一个假象,即每个进程都在独占地使用主存,每个进程看到的内存都是一致的,称为虚拟地址空间。虚拟内存在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,由于每个进程的地址空间一致,从而简化了内存管理,也保护了每个进程的地址空间不被其他进程破坏

操作系统提供一种机制,将不同的进程的虚拟地址和不同内存的物理地址映射起来。当程序访问虚拟地址的时候,由操作系统转换成不同的物理地址。

  • 程序所使用的内存地址叫做虚拟内存地址。

  • 实际存在硬件里面的空间地址叫物理内存地址。

Linux进程的虚拟空间地址如图所示,在Linux中,地址空间最上面的区域是保留给操作系统中的代码和数据的,这对所有进程来说都是一样。地址空间的底部区域存放用户进程定义的代码和数据,注意图中的地址是从下往上增大的

每个进程看到的虚拟地址空间由大量准确定义的区构成,从上到下分别是:

1)程序代码和数据

2)堆

3)共享库

4)栈

5)内核虚拟内存

 

1.2 内存分段

由于程序是由若干个段组成的(栈、段、代码段等),所以操作系统用分段的形式管理物理地址和虚拟地址,虚拟地址通过段表与物理地址映射。但是内存分段存在内存碎片和内存交换效率低的问题。

内存碎片:

  • 外部内存碎片,也就是产生了多个不连续的小物理内存,导致新的程序无法被装载

  • 内部内存碎片,程序所有的内存都被装载到了物理内存,但是这个程序有部分的内存可能并不是很常使用,这也会导致内存的浪费。

例如操作系统空闲内存为256MB,被分成了2段128MB的内存,那么将无法打开一个200MB的程序,如图所示:

解决外部内存碎片的问题就是内存交换。将已经使用的内存一部分写入到硬盘上,再从硬盘读回到内存里,读回时紧挨着最上面的512MB的内存,这样就能空出256MB的连续内存。在Linux系统里,存在内存交换空间,也就是Swap空间,这块空间是从硬盘里划分出来的,用于内存与硬盘的空间交换。

内存交换效率低:

对于多进程的系统,用分段的方式,内存碎片是很容易产生的,产生了内存碎片,那不得不重新Swap内存区域,每一次内存交换,都需要把大段连续的内存数据写到硬盘里上,硬盘的访问速度又很慢,严重影响效率。

 

1.3 内存分页

为了更好的管理内存,操作系统将内存抽象成地址空间。每个程序拥有自己的地址空间,这个地址空间被分割成多个块,每一块称为一页。在Linux下,每一页的大小为4KB。这些页被映射到物理内存,但不需要映射到连续的物理内存,也不需要所有页都必须在物理内存中。当程序引用到不在物理内存中的页时,由硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。虚拟内存允许程序不用将地址空间中的每一页都映射到物理内存,也就是说一个程序不需要全部调入内存就可以运行

虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。每个字节都有唯一的虚拟地址,作为数组的索引。VM系统通过将虚拟内存分割为称为虚拟页的大小固定的块来处理这个问题,类似的,物理内存被分割为物理页。在任意时刻,虚拟页面的稽核都分为三个不想交的子集:

1)未分配的:VM系统还未分配的页,未分配的块没有任务数据和它们相关联,因此也就不占用任何的磁盘空间。

2)缓存的:当前已缓存在物理内存中的已分配页。

3)未缓存的:未缓存在物理内存中的已分配页。

页表是存储在内存的,内存管理单元(MMU)做将虚拟地址转换成物理地址的工作。通常用术语DRAM缓存来表示虚拟内存系统的缓存,它在主存中缓存虚拟页。页表用于将虚拟页映射到物理页,虚拟内存地址分为页号和偏移量,每次地址翻译硬件将一个虚拟地址转换为物理地址时,都会读取页表。页表就是一个页表条目(PTE)的数组。虚拟地址空间中的每个页在页表中一个固定的偏移量处都有一个PTE。PTE是由一个有效位和一个n位地址字段组成的,有效位表明了该虚拟页是否被缓存在DRAM中。从页表查询物理页号,再加上偏移量,即可得到物理内存地址。一个常见的页表如图所示:

上图展示了一个由8个虚拟页和4个物理页的页表。其中:

1)VP 1、VP 2、VP 4和VP 7当前被缓存在DRAM中

2)VP 0和VP 5还未被分配

3)VP3 和VP 6已经被分配了,但还未被缓存。

因为DRAM缓存是全相关联的,所以任意物理页都可以包含任意虚拟页

内存分页是操作系统事先将内存空间分割好的,所以减少了内存碎片,提高了内存利用率。如果内存空间不足,操作系统会将某个内存释放并暂时写到硬盘上,需要的时候再加载进内存,由于每次写入磁盘的只有少数几页,所以内存交换的效率较高。使用分页的方式,也不用一次性把程序都加载到物理内存中,可以在程序运行时再加载。

 

1.4 页面置换算法

在地址映射过程中,若在页面中发现所要访问的页面不在内存中,当操作系统发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间,而用来选择淘汰哪一页的规则叫做页面置换算法。

常见页面置换算法总结如下表:

算法名称 算法规则 算法优缺点
最佳置换算法(OPT) 优先淘汰最长时间内不会被访问的页面 缺页率最小,性能最好;但无法实现
先进先出置换算法(FIFO) 优先淘汰最先进入内存的页面 实现简单;但性能很差,可能出现Belady异常(缺页率提高)
最近最久未使用算法(LRU) 优先淘汰最近最久没访问的页面 性能很好;但需要硬件支持,算法开销大
时钟页面置换算法(Clock) 循环扫描各页面 第一轮淘汰访问位=0的,并将扫描过的页面访问位改为1。若第-轮没选中,则进行第二轮扫描。 实现简单,算法开销小;但未考虑页面是否被修改过。
最不常用法(LFU) 优先淘汰访问次数最少的页面 一个页面在一开始频繁访问,后续就不访问了。会导致内存利用率不高。

 

1.5 Linux虚拟内存系统

Linux主要采用页式内存管理,但是Linux也为每个进程维护了一个单独的虚拟地址空间,形式如图所示。

1)Linux虚拟内存区域

Linux将虚拟内存组织成一些段的集合,一个段就是已经存在着的(已分配的)虚拟内存的连续片。

2)内存映射

Linux通过将一个虚拟内存区域与一个磁盘上的对象关联起来,以初始化这个虚拟区域的内容,这个过程称为内存映射,虚拟内存区域可以映射到如下两种类型的对象中的一种:

  • Linux文件系统中的普通文件。一个区域可以映射到一个普通磁盘文件的连续部分,例如一个可执行目标文件。

  • 匿名文件。一个区域也可以映射到一个匿名文件,匿名文件时由内核创建的,包含的全是二进制零。

 

参考:

  1. 《深入理解计算机系统》

  2. 《图解系统》- 小林coding

 

posted @ 2021-11-08 22:12  烟消00云散  阅读(421)  评论(0编辑  收藏  举报