Categories
不学无术

操作系统中的虚拟内存

某次面试问到了这个问题,回答的不是很好,这两天仔细查了一下,先写下来。当初的问题很简单,就是“What is virtual memory in OS?”

为什么要有虚拟内存?

早期的操作系统是没有虚拟内存的概念的,在实模式(DOS下有的概念,相反的词叫“保护模式”)底下,完全没有什么分段分页或者虚拟地址的概念。这种情况下,内存的操作看起来很直白,程序中对内存的读写就是直接写实际的内存地址。这种直白的带来了很多问题,比如1)操作系统要想执行多进程就比较困难,进程的切换主要方法应该是把当前的进程写入硬盘,然后换个新的程序出来运行。因为所有程序都是直接操作内存,弄不好就崩了;2)如果程序比实际能分配的内存大,那就坑了,程序都载入不了了~
早期某些没有虚拟内存的实模式系统,内存分配的一种情况是这样
[[设备驱动][用户程序][操作系统]]
为了解决第一个问题,引入了内存抽象技术。即每个进程拥有自己的地址,引入了地址空间,操作系统分配给进程的其实是虚拟地址,这些虚拟地址在操作的时候会被转化为实际的物理地址,而这个过程对程序来说是透明的,如下图(来自《Memory management: What every driver writer needs to know》)。
Windows Virtual Memory Address
为了解决第二个问题,引入了虚拟内存技术。

程序的局部性原理

虚拟内存(Virtual Memory) 是指计算机呈现出要比实际拥有的内存大得多的内存量。因此它允许程序员编制并运行比实际系统拥有的内存大得多的程序。这使得许多大型项目也能够在具有有限内存资源的系统上实现。

虚拟内存的可用,个人认为很大程度上依赖于程序的局部性原理。局部性原理分为时间和空间上的局部性:

  1. 最近被访问的程序段在不久的将来还是很容易被访问到;
  2. 在内存中被访问的地址附近的数据在不久的将来也很容易被访问到;

也就是说,在某个特定的事件范围内,有很大比例的内存访问是集中于一小块内存范围内的,这个范围比程序声明要使用的总范围来的小(得多)。

虚拟内存技术

虚拟内存是现代操作系统普遍使用的一种技术。主要的思想很简单,拆东墙补西墙,即把感觉不怎么需要的内存块先写入磁盘,把内存中没有的但亟需使用的内存块调入内存。由于磁盘的容量比内存大很多(虽然磁盘访问的速度比内存慢很多),所以磁盘就成了放置“装不下”的内存块的大备胎。
对于一个程序来说,操作系统分配给他了可操作的地址,操作系统就像管家一样,负责管理内存、磁盘的具体调配(系统调用)。但是至于这段内存地址,实际在操作系统里是放在了内存还是磁盘还是其他什么地方里头,程序就不得而知了,大致就是下图这么个情况吧(来自维基百科)。
虚拟内存
当然这种虚拟内存是有代价的,毕竟磁盘的随机访问速度跟内存还差好几个数量级。因此系统要利用程序的局部性原理,尽量预测未来可能会频繁用到哪些内存,并把他们放入物理内存中。在Win32操作系统下,内存被按照页来分配,一个页是4KB大小。程序在执行的时候,当需要访问某个虚拟地址但是这个页面目前还在磁盘中存储的时候,系统就会产生缺页中断,缺页中断的结果是系统将自认为最近最没机会被访问的页从物理内存中换出(当然如果有空闲内存则没有这个操作),然后把现在急需的页从磁盘中调入。这里就牵扯到换页算法了,一个好的页面调度算法应当尽量减小页面换入换出的次数。
 
 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.