虚拟内存的目的是为了让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。在虚拟内存中,每个程序拥有自己的地址空间,这个地址空间被分割成多个块,每一块称为一页。这些页被映射到物理内存,但不需要映射到连续的物理内存,也不需要所有页都必须在物理内存中。当程序引用到不在物理内存中的页时,由硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。
虚拟内存允许程序不用将地址空间中的每一页都映射到物理内存,也就是说一个程序不需要全部调入内存就可以运行,这使得有限的内存运行大程序成为可能。如有一台计算机可以产生 16 位地址,那么一个程序的地址空间范围是 0~64K。该计算机只有 32KB 的物理内存,虚拟内存技术允许该计算机运行一个 64K 大小的程序。
内存管理单元(MMU)管理着地址空间和物理内存的转换,其中的页表存储着页(程序地址空间)和页框(物理内存空间)的映射表
4KB 的页面仍然是操作系统默认内存页配置的主流。
在程序的运行过程中,如果要访问的页面不在内存中,就发生缺页中断将该页调入内存。如果内存中没有空闲空间,系统需要从内存中调出一个页面来腾出空间。
所选择的被换出的页面是未来最长时间内没有访问的,可保证最低的缺页率 理论上的算法
将最近最久没有使用的页面换出来,是往前看的,最佳算法则是往后看的。可以用链表来实现
每一个页面有两个状态位,R(使用位)和M(修改位)。当页面被访问的时候R=1,当页面被修改的时候M=1. 这样可以将页面分成4类:
R=0,M=0;R=0, M=1;R=1, M=0;R=1, M=1; 发生缺页中断的时候, 首先对页面做顺序扫描,找到R=0,M=0的页面,用于替换如果第1步失败,查找R=0,M=1的页面用于替换,否则跳过。对于跳过的页面,把它的使用位置0.如果还失败,这时候所有页面的使用位都是0了,这时候接着重复第1步,有必要的时候执行第2步。选择换出的页面是最先进入的页面。FIFO有Belady异常,这个异常就是分配的物理块数增大,但是故障数反而增加的异常现象。
用户进程可能有主程序,子程序和数据三部分组成,可以把用户进程划分为3段,每一段从0开始编址,每一段在内存上分配一段连续的空间。这样有利于反映程序的逻辑结构和段的共享。
(1) 在一个进程中,段表只有一个,页表可能有多个。 页式存储能够提高内存的利用率,分段管理能够反映程序的逻辑结构和段的共享,所以就有了段页式的存储管理方式。
先来先服务 按照磁盘请求的顺序进行调度
最短寻道时间 优先选择离当前磁头最近的磁道
电梯算法 从一个方向开始扫描,直到没有请求为止,这时候再调换方向。
(1)系统调用
系统调用的本质其实也是中断,相对于外围设备的硬中断,这种中断称为软中断。这是用户态进程主动要求切换到内核态的一种方式。用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。例如fork()就是执行了一个创建新进程的系统调用。
(2)异常
当cpu在执行运行在用户态下的程序时,发生了一些没有预知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关进程中,也就是切换到了内核态,如缺页异常。
(3)外围设备的中断
当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令而转到与中断信号对应的处理程序去执行,如果前面执行的指令时用户态下的程序,那么转换的过程自然就会是 由用户态到内核态的切换。如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后边的操作等。
这三种方式是系统在运行时由用户态切换到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。从触发方式上看,切换方式都不一样,但从最终实际完成由用户态到内核态的切换操作来看,步骤是一样的,都相当于执行了一个中断响应的过程。系统调用实际上最终是中断机制实现的,而异常和中断的处理机制基本一致。