linux使用什么实现虚拟内存

虚拟内存的实现需要建立在离散分配的内存管理方式的基础上,实现方法有3种:1、请求分页存储管理方式;2、请求分段存储管理方式;3、段页式存储管理方式。不管哪种方式,都需要有一定的硬件支持:1、一定容量的内存和外存;2、页表机制(或段表机制),作为主要的数据结构;3、中断机构,当用户程序要访问的部分尚未调入内存,则产生中断;4、地址变换机构,逻辑地址到物理地址的变换。

linux使用什么实现虚拟内存

程序员必备接口测试调试工具立即使用
Apipost = Postman + Swagger + Mock + Jmeter
Api设计、调试、文档、自动化测试工具
后端、前端、测试,同时在线协作,内容实时同步

本教程操作环境:linux7.3系统、Dell G3电脑。

1. 虚拟内存概述

传统存储管理方式同时将多个进程保存在内存中以便允许多道程序设计。它们都具有以下两个共同的特征:

  • 一次性 作业必须一次性全部装入内存后,方能开始运行。这会导致两种情况发生:
    1)当作业很大,不能全部被装入内存时,将使该作业无法运行;
    2)当大量作业要求运行时,由于内存不足以容纳所有作业,只能使少数作业先运行,导致多道程序度的下降。
  • 驻留性: 作业被装入内存后,就一直驻留在内存中,其任何部分都不会被换出,直至作业运行结束。运行中的进程,会因等待 I/O 而被阻塞,可能处于长期等待状态。

因此,许多在程序运行中不用或暂时不用的程序(数据)占据了大量的内存空间,而一些需要运行的作业又无法装入运行,显然浪费了宝贵的内存资源

1.1 虚拟存储器的定义和特征

基于局部性原理,在程序装入时,可以将程序的一部分装入内存,而将其余部分留在外存,就可以启动程序执行。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。另一方面,操作系统将内存中暂时不使用的内容换出到外存上,从而腾出空间存放将要调入内存的信息。

这样,由于系统提供了部分装入、请求调入和置换功能后(对用户完全透明),给用户的感觉是好像存在一个比实际物理内存大得多的存储器,称为虚拟存储器

虚拟存储器的大小由计算机的地址结构决定,并非是内存和外存的简单相加。

虚拟存储器有以下三个主要特征:

  • 多次性:无需在作业运行时一次性地全部装入内存,而是允许被分成多次调入内存运行。
  • 对换性:无需在作业运行时一直常驻内存,而是允许在作业的运行过程中,进行换进和换出。
  • 虚拟性:从逻辑上扩充内存的容量,使用户所看到的内存容量,远大于实际的内存容量。

1.2 虚拟内存技术的实现

虚拟内存中,允许将一个作业分多次调入内存

釆用连续分配方式时,会使相当一部分内存空间都处于暂时或“永久”的空闲状态,造成内存资源的严重浪费,而且也无法从逻辑上扩大内存容量。

因此,虚拟内存的实现需要建立在离散分配的内存管理方式基础上。虚拟内存的实现有以下三种方式:

  • 请求分页存储管理
  • 请求分段存储管理
  • 段页式存储管理

不管哪种方式,都需要有一定的硬件支持。一般需要的支持有以下几个方面:

  • 一定容量的内存和外存。
  • 页表机制(或段表机制),作为主要的数据结构。
  • 中断机构,当用户程序要访问的部分尚未调入内存,则产生中断。
  • 地址变换机构,逻辑地址到物理地址的变换。

连续分配方式指为一个用户程序分配一个连续的内存空间

  • 固定分区分配:将内存空间划分为若干个固定大小的区域,在每个分区中只装入一道作业,便可以有多道作业并发执行。缺乏灵活性,会产生大量的内部碎片内存的利用率很低
  • 动态分区分配:根据进程的实际需要,动态地为之分配内存空间。作业装入内存时,把可用内存分出一个连续区域给作业,且分区的大小正好合适作业大小的需要。会产生很多外部碎片。

linux使用什么实现虚拟内存

离散分配方式将一个进程分散地装入到许多不相邻的分区中,便可充分地利用内存。

分页存储的概念:

  • 页面、页框和块。进程中的块称为页或页面(Page),具有页号;内存中的块称为页框(Page Frame,页框=内存块=物理块=物理页面,具有页框号。外存也以同样的单位进行划分,直接称为块(Block)。进程在执行时需要申请主存空间,就是要为每个页面分配主存中的可用页框,这就产生了页和页框的一一对应。各个页面不必连续存放,可以放到不相邻的各个页框中。
  • 地址结构:前一部分为页号P,后一部分为页内偏移量W。地址长度为32 位,其中0~11位为页内地址,即每页大小为4KB;12~31位为页号,地址空间最多允许有2^20页。
  • 页表。为了便于在内存中找到进程的每个页面所对应的物理块,系统为每个进程建立一张页表,记录页面在内存中对应的物理块号,页表一般存放在内存中。在配置了页表后,进程执行时,通过查找该表,即可找到每页在内存中的物理块号。可见,页表的作用是实现从页号到物理块号的地址映射

linux使用什么实现虚拟内存

2. 请求分页管理方式实现虚拟内存

请求分页是目前最常用的一种实现虚拟存储器的方法。

请求分页系统建立在基本分页系统基础之上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能。

在请求分页系统中,只要求将当前需要的一部分页面装入内存,便可以启动作业运行。
在作业执行过程中,当所要访问的页面不在内存时,再通过调页功能将其调入,同时还可以通过置换功能将暂时不用的页面换出到外存上,以便腾出内存空间。

为了实现请求分页,系统必须提供一定的硬件支持。除了需要一定容量的内存及外存的计算机系统,还需要有页表机制、缺页中断机构、地址变换机构

2.1 页表机制

请求分页系统的页表机制不同于基本分页系统,请求分页系统在一个作业运行之前不要求全部一次性调入内存。

因此在作业的运行过程中,必然会出现要访问的页面不在内存的情况,如何发现和处理这种情况是请求分页系统必须解决的两个基本问题。为此,在请求页表项中增加了四个字段,分别为:

请求分页系统中的页表项
页号 物理块号 状态位 P 访问字段 A 修改位 M 外存地址
  • 状态位 P:用于指示该页是否已调入内存,供程序访问时参考。
  • 访问字段 A:用于记录本页在一段时间内被访问的次数,或记录本页最近己有多长时间未被访问,供置换算法换出页面时参考。
  • 修改位 M:标识该页在调入内存后是否被修改过。
  • 外存地址:用于指出该页在外存上的地址,通常是物理块号,供调入该页时参考。

2.2 缺页中断机构

在请求分页系统中,每当所要访问的页面不在内存时,便产生一个缺页中断,请求操作系统将所缺的页调入内存。

此时应将缺页的进程阻塞(调页完成唤醒),如果内存中有空闲块,则分配一个块,将要调入的页装入该块,并修改页表中相应页表项;若此时内存中没有空闲块,则要淘汰某页(若被淘汰页在内存期间被修改过,则要将其写回外存)。

缺页中断作为中断同样要经历,诸如保护CPU环境、分析中断原因、转入缺页中断处理程序、恢复CPU环境等几个步骤。但与一般的中断相比,它有以下两个明显的区别:

  • 在指令执行期间产生和处理中断信号,而非一条指令执行完后,属于内部中断。
  • 一条指令在执行期间,可能产生多次缺页中断。

2.3 地址变换机构

请求分页系统中的地址变换机构,是在分页系统地址变换机构的基础上,为实现虚拟内存,又增加了某些功能而形成的。

linux使用什么实现虚拟内存
请求分页中的地址变换过程

在进行地址变换时,先检索快表

  • 若找到要访问的页,便修改页表项中的访问位(写指令则还须重置修改位),然后利用页表项中给出的物理块号和页内地址形成物理地址。
  • 若未找到该页的页表项,应到内存中去查找页表,再对比页表项中的状态位P,看该页是否已调入内存,未调入则产生缺页中断,请求从外存把该页调入内存。

页表指出逻辑地址中的页号与所占主存物理块号的对应关系。页式存储管理在用动态重定位方式装入作业时,要利用页表做地址转换工作。

快表(TLB,Translation Lookaside Buffer)就是存放在高速缓冲存储器的部分页表。作为当前进程页表的Cache,它的作用与页表相似,但加快了地址映射速度,提高了访问速率。

由于采用页表做地址转换,读写内存数据时CPU要访问两次主存(查询页表、访问目的地址)。

有了快表,有时只要访问一次高速缓冲存储器,一次主存,这样可加速查找并提高指令执行速度。

3. 页面置换算法

进程运行时,若其访问的页面不在内存而需将其调入,但内存已无空闲空间时,就需要从内存中调出一页程序或数据,送入磁盘的对换区。

选择调出页面的算法就称为页面置换算法。好的页面置换算法应有较低的页面更换频率,也就是说,应将以后不会再访问或者以后较长时间内不会再访问的页面先调出。

3.1 最佳置换算法(OPT)

最佳(Optimal, OPT)置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。

但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现,但最佳置换算法可以用来评价其他算法

假定系统为某进程分配了三个物理块,并考虑有以下页面号引用串:
7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1

进程运行时,先将7, 0, 1三个页面依次装入内存。进程要访问页面2时,产生缺页中断,根据最佳置换算法,选择第18次访问才需调入的页面7予以淘汰。然后,访问页面0时,因为已在内存中所以不必产生缺页中断。访问页面3时又会根据最佳置换算法将页面1淘汰……依此类推。从图中可以看出釆用最佳置换算法时的情况。

利用最佳置换算法时的置换图
访问页面 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
物理块1 7 7 7 2 2 2 2 2 7
物理块2 0 0 0 0 4 0 0 0
物理块3 1 1 3 3 3 1 1
缺页否

可以看到,发生缺页中断的次数为9,页面置换的次数为6。

3.2 先进先出(FIFO)页面置换算法

优先淘汰最早进入内存的页面,亦即在内存中驻留时间最久的页面。

该算法实现简单,只需把调入内存的页面根据先后次序链接成队列,设置一个指针总指向最早的页面。但该算法与进程实际运行时的规律不适应,因为在进程中,有的页面经常被访问。

利用FIFO置换算法时的置换图
访问页面 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
物理块1 7 7 7 2 2 2 4 4 4 0 0 0 7 7 7
物理块2 0 0 0 3 3 3 2 2 2 1 1 1 0 0
物理块3 1 1 1 0 0 0 3 3 3 2 2 2 1
缺页否

利用FIFO算法时进行了 12 次页面置换,比最佳置换算法正好多一倍。

FIFO算法还会产生当所分配的物理块数增大而页故障数不减反增的异常现象,这是由 Belady于1969年发现,故称为Belady异常,如下表所示。

访问页面 1 2 3 4 1 2 5 1 2 3 4 5
物理块1 1 1 1 4 4 4 5 5 5
物理块2 2 2 2 1 1 1 3 3
物理块3 3 3 3 2 2 2 4
缺页否
增加物理块数后对比
物理块1* 1 1 1 1 5 5 5 5 4 4
物理块2* 2 2 2 2 1 1 1 1 5
物理块3* 3 3 3 3 2 2 2 2
物理块4* 4 4 4 4 3 3 3
缺页否

只有FIFO算法可能出现Belady异常,而LRU和OPT算法永远不会出现Belady异常。

3.3 最近最久未使用(LRU)置换算法

最近最久未使用(LRU,Least Recently Used)置换算法选择最近最长时间未访问过的页面予以淘汰,它认为过去一段时间内未访问过的页面,在最近的将来可能也不会被访问。

该算法为每个页面设置一个访问字段,来记录页面自上次被访问以来所经历的时间,淘汰页面时选择现有页面中值最大的予以淘汰。

LRU页面置换算法时的置换图
访问页面 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
物理块1 7 7 7 2 2 4 4 4 0 1 1 1
物理块2 0 0 0 0 0 0 3 3 3 0 0
物理块3 1 1 3 3 2 2 2 2 2 7
缺页否

LRU性能较好,但需要寄存器和栈的硬件支持,开销更大。

LRU是堆栈类的算法。理论上可以证明,堆栈类算法不可能出现Belady异常。FIFO算法基于队列实现,不是堆栈类算法。

3.4 时钟(CLOCK)置换算法

LRU算法的性能接近于OPT,但是实现起来比较困难,且开销大;FIFO算法实现简单,但性能差。所以操作系统的设计者尝试了很多算法,试图用比较小的开销接近LRU的性能,这类算法都是CLOCK算法的变体。

简单的CLOCK算法是给每一帧关联一个附加位,称为使用位。当某一页首次装入主存,以及后续被访问时,使用位被置为1。

对于页替换算法,用于替换的候选帧集合看做一个循环缓冲区,并且有一个指针与之相关联。当某一页被替换时,该指针被设置成指向缓冲区中的下一帧。

当需要替换一页时,操作系统扫描缓冲区,以查找第一个使用位为0的一帧。每当遇到一个使用位为1的帧时,操作系统就将该位重新置为0;如果所有帧的使用位均为1,则指针在缓冲区中完整地循环一周,把所有使用位都置为0,并且停留在最初的位置上,替换该帧中的页。由于该算法循环地检查各页面的情况,故称为CLOCK算法,又称为最近未用(Not Recently Used, NRU)算法。

CLOCK算法的性能比较接近LRU,而通过增加使用的位数目,可以使得CLOCK算法更加高效。在使用位used的基础上再增加一个修改位modified,则得到改进型的CLOCK置换算法。

每一帧都处于以下四种情况之一:

  • 最近未被访问,也未被修改(u=0, m=0)。

  • 最近被访问,但未被修改(u=1, m=0)。

  • 最近未被访问,但被修改(u=0, m=1)。

  • 最近被访问,被修改(u=1, m=1)。

算法执行如下操作步骤:

  • 从指针的当前位置开始,扫描帧缓冲区。在这次扫描过程中,对使用位不做任何修改。选择遇到的第一个帧(u=0, m=0)用于替换。

  • 如果第1步失败,则重新扫描,查找(u=0, m=1)的帧。选择遇到的第一个这样的帧用于替换。在这个扫描过程中,对每个跳过的帧,把它的使用位设置成0。

  • 如果第2步失败,指针将回到它的最初位置,并且集合中所有帧的使用位均为0。重复第1步,并且如果有必要,重复第2步。这样将可以找到供替换的帧。

改进型的CLOCK算法优于简单CLOCK算法之处在于替换时首选没有变化的页。由于修改过的页在被替换之前必须写回,因而这样做会节省时间。

4. 页面分配策略

4.1 驻留集大小

对于分页式的虚拟内存,在准备执行时,不需要也不可能把一个进程的所有页都读取到主存,因此,操作系统必须决定读取多少页。也就是说,给特定的进程分配多大的主存空间,这需要考虑以下几点:

  • 分配给一个进程的存储量越小,在任何时候驻留在主存中的进程数就越多,从而可以提高处理机的时间利用效率。

  • 如果一个进程在主存中的页数过少,尽管有局部性原理,页错误率仍然会相对较高。

  • 如果页数过多,由于局部性原理,给特定的进程分配

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发