在C语言里面是按照行优先来放置二维数组,a0,0->a0,1023 a1,0->a1,1023......
上图第一行,从a0,0->a0,1023其实已经占了一个页了,所以如果数组的数据还在硬盘当中,当它第一次访问的时候,数据还不在内存中,所以会产生一个缺页异常,操作系统就会把这个4K的数据块放到内存中来,那么程序1会访问到a0,0,这时候可以正常访问,访问之前产生了一次缺页异常,第二次访问的是a1,0,从位置上来说a1,0和a0,0差了4K(一个int占4个字节)这么大的一个距离,这个数据其实也在硬盘上,这个时候可以看出来在一个很短的事件内,它访问的两个数据,隔得很远,不具有前面所说的时间局部性也不具有空间局部性,使得操作系统不得不把另一个4K数据块导入到内存中,又产生一次中断,以此类推,共产生1024X1024次缺页中断,意味着在当前特定情况下,没进行一次访问就会产生一次中断。每产生一次中断就会完成从硬盘到内存的读写操作,可以看到开销是非常大的。
第二个程序,按照列来访问的,a0,0,a0,1.....a0,1023,当第一次访问,跟程序1一样,数据在硬盘上,会产生一次中断,接下来操作系统会把数据从硬盘导到内存中去,接下来访问a0,1,这个位置是紧接着a0,0的,它具有很好的空间局部性和时间局部性,那么a0,0,a0,1.....a0,1023这一行都不会产生中断,这一个4K页访问都不会产生中断,这样只会产生1024次中断。开销远远小于程序1
如果设计一个程序都不具备局部性,操作系统就很难推测出来,应该把哪些数据和代码放到内存中去,正是因为有了局部性,是的操作系统可以认为,当前这在访问的,数据和代码,在一段很短时间内,它旁边靠近的数据和代码都看会被访问,它根据这个原理做出选择,应该把哪些代码和数据放到内存中去。
要实现高效虚存管理技术,除了操作系统和硬件外,还需要我们的程序有一定的局部性,如果不具备局部性,高效实现起来很困难。
注意一点,操作系统内核是不能被换出的,需要常驻内存。
上图第三个,不连续的,体现在什么地方?物理内存分配不连续,同时,虚拟空间使用也是不连续的,这个前面章节说的有个对照,之前将的虚拟内存是连续的,在这里由于有换入换出机制,可能把虚拟空间连续的区域中的一部分换出到外存中去了,使得实际执行过程中,可能会出现,执行到某阶段,会出现这个页不存在,这种情况下就会产生访问异常,这个异常,重装系统会自动处理,会把需要连续执行的代码和数据重新加载到内存,从而使得程序继续执行。
上图所示,虚拟内存的具体实现,以页内存管理为基础讲解。
PTBR 页表基址寄存器