1.背景
实际情况下,程序不必全部放到内存中。例如
程序处理异常错误条件的代码,因为这些错误很少发生
数组、表等分配了比实际所需的更多内存。声明一个100*100的数组,可能实际用到的只是10*10
程序的某些选项或功能很少用。
虚拟内存将用户逻辑内存与物理内存分开。虚拟内存使编程更加容易,程序员不必担心有限的物理内存
如图允许随着动态分配,堆可以向上生长,类似的栈可以向下生长。堆与栈之间的巨大空间为虚拟地址的比部分。只有在堆与栈生长时,才需要实际的物理页。包含空白的虚拟地址空间称为稀虚拟地址空间。
除了将逻辑内存与物理内存分开,虚拟内存也允许文件和内存通过共享页而为多个进程所共享
2.按需调页
一个执行程序可全部载入内存,也可在需要时才调用相应的页。这种方法称为按需调页。这种方法对单个页操作,
2.1基本概念
需要一定的硬件支持来区分哪些页在内存,那些页在磁盘。可以用页表中的位来表示:有效位,相关的页在内存中;无效位,不在进程的 逻辑地址空间。
当进程试图访问未调到内存的页时,对标记为无效的访问会产生页错误陷阱。
从理论上讲,程序的某条指令可能访问多个页的内存,从而产生多个页错误。然而这种情况很少见。
支持按需调页的硬件与分页和交换的硬件一样:页表和次级存储器。
请求调页的 关键要求是能在页错误后重新执行命令。出现页错误时,保存中断进程的状态(寄存器、条件代码、指令计数器)。
3.写时复制
父进程通过fork()复制自己的地址空间创建新进程。然而许多子进程在创建时会马上执行exec(),因此父进程的复制可能没有必要,因此可以使用一种写时复制的技术。这种方法允许父进程与子进程开始时共享同一页面。这些页面标记为写时复制页。
4.页面置换
在地址映射过程中,若在页面中发现所要访问的页面不再内存中,则产生缺页中断。当发生缺页中断时操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。
1.基本页置换
如果没有空闲帧,那么就查找当前没有使用的帧,并将其释放。可采用这样的方式释放一个帧:将其内容写到交换空间,并改变其页表以表示该页不在内存中。现在可用使用空闲帧来保存进程出错的页。重启用户进程。
5.帧分配
如何在各个进程之间分配一定的空闲内存?如果有93个空闲帧和2个进程,每个进程应得到多少帧呢?考虑一个单用户系统,页大小为1KB,其总内存为128KB,因此共有128个帧。操作系统可能使用35个帧,用户进程使用93个帧。如采用纯按需调用,那么开始时93页帧都位于空闲链表上。当用户进程开始执行时,它会产生一系列的页错误。头93页错误会从空闲帧链表中获得帧。当空闲帧链表用完后,必须使用页置换算法以从内存中的93个页选择一个置换为第94页。以此类推,当进程终止时,这93个帧将再次放在空闲帧链表上。
5.1.帧的最少数量
如果分配给每个进程的帧数量较少的话,页错误会相应增加,从而减慢进程的执行。
8.内核中的分配
当用户进程需要额外内存时,可以从内核所维护的空闲页来获取页。该链表通常用替换算法来更新。