热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

虚拟内存实现分页相关工作、缺页中断处理、指令备份、锁定内存中的页面、后备存储、策略和机制的分离

3.6有关实现的问题实现虚拟内存系统要在主要的理论算法(如第二次机会算法与老化算法,局部页面分配与全局页面分配,请求调页与预先调页&#x

3.6   有关实现的问题

实现虚拟内存系统要在主要的理论算法(如第二次机会算法与老化算法,局部页面分配与全局页面分配,请求调页与预先调页)之间进行选择。但同时也要注意一系列实际的实现问题。

3.6.1   与分页有关的工作

操作系统要在下面的四段时间里做与分页相关的工作:进程创建时,进程执行时,缺页中断时和进程终止时。

当在分页系统中创建一个新进程时,操作系统要确定程序和数据在初始时有多大,并为它们创建一个页表。操作系统还要在内存中为页表分配空间并对其进行初始化。当进程被换出时,页表不需要驻留在内存中,但当进程运行时,它必须在内存中。另外,操作系统要在磁盘交换区中分配空间,以便在一个进程换出时在磁盘上有放置此进程的空间。操作系统还要用程序正文和数据对交换区进行初始化,这样当新进程发生缺页中断时,可以调入需要的页面某些系统直接从磁盘上的可执行文件对程序正文进行分页,以节省磁盘空间和初始化时间。最后,操作系统必须把有关页表和磁盘交换区的信息存储在进程表中

调度一个进程执行时,必须为新进程重置MMU,刷新TLB,以清除以前的进程遗留的痕迹新进程的页表必须成为当前页表,通常可以通过复制该页表或者把一个指向它的指针放进某个硬件寄存器来完成。有时,在进程初始化时可以把进程的部分或者全部页面装入内存中以减少缺页中断的发生,例如,PC(程序计数器)所指的页面肯定是需要的。

缺页中断发生时,操作系统必须通过读硬件寄存器来确定是哪个虚拟地址造成了缺页中断。通过该信息,它要计算需要哪个页面,并在磁盘上对该页面进行定位。它必须找到合适的页框来存放新页面,必要时还要置换老的页面,然后把所需的页面读入页框。最后,还要备份程序计数器,使程序计数器指向引起缺页中断的指令,并重新执行该指令。

进程退出的时候,操作系统必须释放进程的页表、页面和页面在硬盘上所占用的空间。如果某些页面是与其他进程共享的,当最后一个使用它们的进程终止的时候,才可以释放内存和磁盘上的页面。

3.6.2   缺页中断处理

缺页中断发生时的事件顺序如下:

1) 硬件陷入内核,在堆栈中保存程序计数器。大多数机器将当前指令的各种状态信息保存在特殊的CPU寄存器中。

2) 启动一个汇编代码例程保存通用寄存器和其他易失的信息,以免被操作系统破坏。这个例程将操作系统作为一个函数来调用。

3) 当操作系统发现一个缺页中断时,尝试发现需要哪个虚拟页面。通常一个硬件寄存器包含了这一信息,如果没有的话,操作系统必须检索程序计数器,取出这条指令,用软件分析这条指令,看看它在缺页中断时正在做什么。

4) 一旦知道了发生缺页中断的虚拟地址,操作系统检查这个地址是否有效,并检查存取与保护是否一致。如果不一致,向进程发出一个信号或杀掉该进程。如果地址有效且没有保护错误发生,系统则检查是否有空闲页框。如果没有空闲页框,执行页面置换算法寻找一个页面来淘汰。

5) 如果选择的页框“脏”了,安排该页写回磁盘,并发生一次上下文切换,挂起产生缺页中断的进程,让其他进程运行直至磁盘传输结束。无论如何,该页框被标记为忙,以免因为其他原因而被其他进程占用。

6) 一旦页框“干净”后(无论是立刻还是在写回磁盘后),操作系统查找所需页面在磁盘上的地址,通过磁盘操作将其装入。该页面被装入后,产生缺页中断的进程仍然被挂起,并且如果有其他可运行的用户进程,则选择另一个用户进程运行。

7) 当磁盘中断发生时,表明该页已经被装入,页表已经更新可以反映它的位置,页框也被标记为正常状态

8) 恢复发生缺页中断指令以前的状态,程序计数器重新指向这条指令。

9) 调度引发缺页中断的进程,操作系统返回调用它的汇编语言例程

10) 该例程恢复寄存器和其他状态信息,返回到用户空间继续执行,就好像缺页中断没有发生过一样。

3.6.3   指令备份

当程序访问不在内存中的页面时,引起缺页中断的指令会半途停止并引发操作系统的陷阱。在操作系统取出所需的页面后,它需要重新启动引起陷阱的指令。但这并不是一件容易实现的事。

我们在最坏情形下考察这个问题的实质,考虑一个有双地址指令的CPU,比如Motorola 680x0,这是一种在嵌入式系统中广泛使用的CPU。例如,指令


  1. MOVE.L#6(A1), 2(A0) 

为6字节(见图3-28)。为了重启该指令,操作系统要知道该指令第一个字节的位置。在陷阱发生时,程序计数器的值依赖于引起缺页中断的那个操作数以及CPU中微指令的实现方式。


 

在图3-28中,从地址1000处开始的指令进行了3次内存访问:指令字本身和操作数的2个偏移量。从可以产生缺页中断的这3次内存访问来看,程序计数器可能在1000、1002和1004时发生缺页中断,对操作系统来说要准确地判断指令是从哪儿开始的通常是不可能的。如果发生缺页中断时程序计数器是1002,操作系统无法弄清在1002位置的字是与1000的指令有关的内存地址(比如,一个操作数的位置),还是一个指令的操作码。

这种情况已经很糟糕了,但可能还有更糟的情况。一些680x0体系结构的寻址方式采用自动增量,这也意味着执行这条指令的副作用是会增量一个或多个寄存器。使用自动增量模式也可能引起错误。这依赖于微指令的具体实现,这种增量可能会在内存访问之前完成,此时操作系统必须在重启这条指令前将软件中的寄存器减量。自动增量也可能在内存访问之后完成,此时,它不会在陷入时完成而且不必由操作系统恢复。自动减量也会出现相同的问题。自动增量和自动减量是否在相应访存之前完成随着指令和CPU模式的不同而不同。

幸运的是,在某些计算机上,CPU的设计者们提供了一种解决方法,就是通过使用一个隐藏的内部寄存器。在每条指令执行之前,把程序计数器的内容复制到该寄存器。这些机器可能会有第二个寄存器,用来提供哪些寄存器已经自动增加或者自动减少以及增减的数量等信息。通过这些信息,操作系统可以消除引起缺页中断的指令所造成的所有影响,并使指令可以重新开始执行。如果该信息不可用,那么操作系统就要找出所发生的问题从而设法来修复它。看起来硬件设计者是不能解决这个问题了,于是他们就推给操作系统的设计者来解决这个问题。

3.6.4   锁定内存中的页面

计算机有虚拟内存并不意味着I/O不起作用了。虚拟内存和I/O通过微妙的方式相互作用着。设想一个进程刚刚通过系统调用从文件或其他设备中读取数据到其地址空间中的缓冲区。在等待I/O完成时,该进程被挂起,另一个进程被允许运行,而这个进程产生一个缺页中断。

如果分页算法是全局算法,包含I/O缓冲区的页面会有很小的机会(但不是没有)被选中换出内存。如果一个I/O设备正处在对该页面进行DMA传输的过程之中,将这个页面移出将会导致部分数据写入它们所属的缓冲区中,而部分数据被写入到最新装入的页面中。一种解决方法是锁住正在做I/O操作的内存中的页面以保证它不会被移出内存。锁住一个页面通常称为在内存中钉住(pinning)页面。另一种方法是在内核缓冲区中完成所有的I/O操作,然后再将数据复制到用户页面。

3.6.5   后备存储

在页面置换算法中,已经知道如何选择换出内存的页面。但是却没有讨论当页面被换出时会存放在磁盘上的哪个位置。磁盘管理相关的问题:

在磁盘上分配页面空间的最简单的算法是在磁盘上设置特殊的交换分区,甚至从文件系统划分一块独立的磁盘(以平衡I/O负载)。大多数UNIX是这样处理的。在这个分区里没有普通的文件系统,这样就消除了将文件偏移转换成块地址的开销。取而代之的是,始终使用相应分区的起始块号。

当系统启动时,该交换分区为空,并在内存中以单独的项给出它的起始和大小。在最简单的情况下,当第一个进程启动时,留出与这个进程一样大的交换区块,剩余的为总空间减去这个交换分区。当新进程启动后,它们同样被分配与其核心映像同等大小的交换分区。进程结束后,会释放其磁盘上的交换区。交换分区以空闲块列表的形式组织。更好的算法在第10章里讨论。

与每个进程对应的是其交换区的磁盘地址,即进程映像所保存的地方。这一信息是记录在进程表里的。写回一个页面时,计算写回地址的过程很简单:将虚拟地址空间中页面的偏移量加到交换区的开始地址。但在进程启动前必须初始化交换区,一种方法是将整个进程映像复制到交换区,以便随时可将所需内容装入,另一种方法是将整个进程装入内存,并在需要时换出

但这种简单模式有一个问题:进程在启动后可能增大,尽管程序正文通常是固定的,但数据有时会增长,堆栈也总是在随时增长。这样,最好为正文、数据和堆栈分别保留交换区,并且允许这些交换区在磁盘上多于一个块

另一个极端的情况是事先什么也不分配,在页面换出时为其分配磁盘空间,并在换入时回收磁盘空间,这样内存中的进程不必固定于任何交换空间。其缺点是内存中每个页面都要记录相应的磁盘地址。换言之,每个进程都必须有一张表,记录每一个页面在磁盘上的位置。这两个方案如图3-29所示。


 

在图3-29a中,有一个带有8个页面的页表。页面0、3、4和6在内存中。页面1、2、5和7在磁盘上。磁盘上的交换区与进程虚拟地址空间(8页面)一样大,每个页面有固定的位置,当它从内存中被淘汰时,便写到相应位置。该地址的计算需要知道进程的分页区域的起始位置,因为页面是按照它们的虚拟页号的顺序连续存储的。内存中的页面通常在磁盘上有镜像副本,但是如果页面装入后被修改过,那么这个副本就可能是过期的了。内存中的深色页面表示不在内存,磁盘上的深色页面(原则上)被内存中的副本所替代,但如果有一个内存页面要被换回磁盘并且该页面在装入内存后没有被修改过,那么将使用磁盘中(深色)的副本。

在图3-29b中,页面在磁盘上没有固定地址。当页面换出时,要及时选择一个空磁盘页面并据此来更新磁盘映射(每个虚拟页面都有一个磁盘地址空间)。内存中的页面在磁盘上没有副本。它们在磁盘映射表中的表项包含一个非法的磁盘地址或者一个表示它们未被使用的标记位。

不能保证总能够实现固定的交换分区。例如,没有磁盘分区可用时。在这种情况下,可以利用正常文件系统中的一个或多个较大的、事前定位的文件。Windows就使用这个方法。然而,可以利用优化方法减少所需的磁盘空间量。既然每个进程的程序正文来自文件系统中某个(可执行的)文件,这个可执行文件就可用作交换区。而更好的方法是,由于程序正文通常是只读的,当内存资源紧张、程序页不得不移出内存时,尽管丢弃它们,在需要的时候再从可执行文件读入即可。共享库也可以用这个方式工作。

3.6.6   策略和机制的分离

控制系统复杂度的一种重要方法就是把策略从机制中分离出来。通过使大多数存储管理器作为用户级进程运行,就可以把该原则应用到存储管理中。

一个如何分离策略和机制的简单例子可以参见图3-30。其中存储管理系统被分为三个部分:

1) 一个底层MMU处理程序

2) 一个作为内核一部分的缺页中断处理程序

3) 一个运行在用户空间中的外部页面调度程序

所有关于MMU工作的细节都被封装在MMU处理程序中,该程序的代码是与机器相关的,而且操作系统每应用到一个新平台就要被重写一次。缺页中断处理程序是与机器无关的代码,包含大多数分页机制。策略主要由作为用户进程运行的外部页面调度程序所决定。


 

当一个进程启动时,需要通知外部页面调度程序以便建立进程页面映射,如果需要的话还要在磁盘上分配后备存储。当进程正在运行时,它可能要把新对象映射到它的地址空间,所以还要再一次通知外部页面调度程序。

一旦进程开始运行,就有可能出现缺页中断。缺页中断处理程序找出需要哪个虚拟页面,并发送一条消息给外部页面调度程序告诉它发生了什么问题。外部页面调度程序从磁盘中读入所需的页面,把它复制到自己的地址空间的某一位置。然后告诉缺页中断处理程序该页面的位置。缺页中断处理程序从外部页面调度程序的地址空间中清除该页面的映射,然后请求MMU处理程序把它放到用户地址空间的正确位置,随后就可以重新启动用户进程了。

这个实现方案没有给出放置页面置换算法的位置。把它放在外部页面调度程序中比较简单,但会有一些问题。这里有一条原则就是外部页面调度程序无权访问所有页面的R位和M位。这些二进制位在许多页面置换算法起重要作用。这样就需要有某种机制把该信息传递给外部页面调度程序,或者把页面置换算法放到内核中。在后一种情况下,缺页中断处理程序会告诉外部页面调度程序它所选择的要淘汰的页面并提供数据,方法是把数据映射到外部页面调度程序的地址空间中或者把它包含到一条消息中。两种方法中,外部页面调度程序都把数据写到磁盘上。

这种实现的主要优势是有更多的模块化代码和更好的适应性。主要缺点是由于多次交叉“用户-内核”边界引起的额外开销,以及系统模块间消息传递所造成的额外开销。现在看来,这一主题有很多争议,但是随着计算机越来越快,软件越来越复杂,从长远来看,对于大多数实现,为了获得更高的可靠性而牺牲一些性能也是可以接受的。




推荐阅读
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 如何用JNI技术调用Java接口以及提高Java性能的详解
    本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了2020年计算机二级MSOffice的选择习题及答案,详细解析了操作系统的五大功能模块,包括处理器管理、作业管理、存储器管理、设备管理和文件管理。同时,还解答了算法的有穷性的含义。 ... [详细]
  • 服务器上的操作系统有哪些,如何选择适合的操作系统?
    本文介绍了服务器上常见的操作系统,包括系统盘镜像、数据盘镜像和整机镜像的数量。同时,还介绍了共享镜像的限制和使用方法。此外,还提供了关于华为云服务的帮助中心,其中包括产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题和视频帮助等技术文档。对于裸金属服务器的远程登录,本文介绍了使用密钥对登录的方法,并提供了部分操作系统配置示例。最后,还提到了SUSE云耀云服务器的特点和快速搭建方法。 ... [详细]
author-avatar
恋若寒1999
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有