一、CPU的访存路径
上图是目前主流的CPU架构介绍。可以看到,CPU的访存路径:先经过MMU,然后经过Cache,最后到达DRAM。这其中涉及到的关键内容为基于MMU的内存管理以及缓存机制。
1.1、基于MMU的内存管理
众所周知,在计算机设计之处是没有虚拟地址的概念的,CPU发出的地址即是物理地址,其访存行为类似与目前熟知的单片机。
在早期,使用DOS或是更古老的操作系统的时,计算机的内存还非常小,一般都是以K为单位进行计算。相应的,当时的程序规模也不大,整体适配可以看到内存容量虽然小,但还是可以容纳当时的程序。
随着图形界面的兴起,以及用户需求的不断增大,应用程序的规模也随之扩张,以至于内存容纳不下更大规模的程序。如何在有限的内存资源上运行大体积的程序逐渐成为亟待解决的难题。为此,发展出了ovelay技术,即开发者对程序预先进行分割、实现分段运行,并由系统或者主控程序或者程序内生代码逻辑将需要运行代码段换入内存并覆盖目前不再使用的旧的代码段。如此反复的按需的将对应代码段载入并运行。
DOS系统发展史DOS是Disk Operation System(磁盘操作系统)的简称,是个人计算机上的一类操作系统。它直接操纵管理硬盘的文件,一般都是黑底白色文字的界面。从1980年到1995年的15年间,DOS在IBM PC兼容机市场中占有举足轻重的地位。当时,电脑操作系统就是DOS,键入DOS命令运行,其他应用程序,都是在DOS界面下键入EXE或BAT文件运行。早期的DOS系统是由微软公司为IBM的个人计算机开发的,称为MS-DOS。后来,其他公司生产的与MS-DOS兼容的操作系统,也延用了这个称呼,如PC-DOS、R-DOS等等。磁盘操作系统是单用户、单工的操作系统,拥有不可重入的基本核心函数(意即同时间只能有一个程序调用这些函数)。有一个例外的状况,就是常驻程序(Terminate and Stay Resident,缩写为 TSR)。某些常驻程序允许用户多任务操作;然而此时仍有“核心不可重入”的问题:当一个进程 (process) 调用了操作系统核心中的服务函数(也就是系统调用)时,在这个调用退出之前,其他的进程绝对不能进行系统调用、打断第一个进程。1980-1981年,西雅图电脑产品公司程序员蒂姆·帕特森(Tim Paterson)花费了四个月时间编写出了86-DOS操作系统。1981年7月,微软以五万美元的代价向西雅图公司购得本产品的全部版权,并将它更名为MS-DOS。随后,IBM发布了第一台个人计算机,当时采用的操作系统是西雅图公司的86-DOS 1.14,但微软很快改进了MS-DOS,并使它成功地成为IBM PC采用的操作系统。并于1981年8月12日,正式发布MS-DOS 1.0和PC-DOS 1.0。DOS 1.0 微软买下 86-DOS(Qdos)版权。1981年7月成为IBM PC上 第一个作业系统。同时微软又为IBM PC开发专用版本 PC-DOS,但与泛用版本DOS相比,除了系统档名以及部份针对 IBM 机器设计的核心,外部命令与公用程式之外,其余程式码差异不大。DOS 1.25 1982年6月,支持双面软盘并开始修复bug。不仅IBM,MS,许多OEM也广泛使用。DOS 2.0 1983年3月,是一次重大改版,正式采用了文件配置表格式,并大量使用具有UNIX特性的Handle式文件操作方式。DOS 3.0 增加了对新的IBM AT硬件以及部分局域网功能的支持。DOS 3.1 增加了更多局域网功能支持。DOS 3.2 1986年,支持720K的5寸软盘。DOS 3.3 1987年,支持新的IBM PS/2设备以及1.44M的3寸软盘,并支持其它语言的字符集。DOS 4.0 1988年,增加了DOSSHELL操作环境,并且有一些其它增强功能及更新。DOS 5.0 1991年发行,新增了很好的内存管理和宏功能,增强了DOSSHELL。DOS 6.x 1993年发行,大量增加图形界面程序(如SCANDISK,DEFRAG,MSBACKUP等),增加了对586计算机,磁盘压缩等功能的支持,增强了对Windows的支持。DOS 7.0 1995年发行,增加了长文件名,LBA大硬盘等功能,增强了对新版Windows的支持,并加强了一些命令。DOS 7.1 1996年8月,全面支持FAT32分区、大硬盘、大内存等,并更新了一些功能,如四位年份的支持等,是目前最实用的DOS版本。DOS 8.0 2000年发行,是MS-DOS的最后一个版本。由于微软看到了Windows的曙光,于是放弃了DOS。
但是,ovelay技术只是短时间内缓解了矛盾。在ovelay技术中,覆盖块0首先运行,结束时他将调用另一个覆盖块。虽然覆盖块的交换是由OS完成的,但是必须先由程序员把程序先进行分割,这是一个复杂且耗时的过程,并且限制了程序逻辑。
因此亟需找到更好的办法从而在根本上解决这个问题。后来诞生了
虚拟存储器(virtual memory)技术。虚拟存储器的基本思想是程序、数据、堆栈的总的大小可以超过物理存储器的大小,操作系统把当前使用的部分保留在内存中,而把其他未被使用的部分保存在磁盘上。比如对一个16MB的程序和一个内存只有4MB的机器,操作系统通过选择,可以决定各个时刻将哪4M的内容保留在内存中,并在需要时在内存和磁盘间交换程序片段,这样就可以把这个16M的程序运行在一个只具有4M内存机器上了。而这个16M的程序在运行前不必由程序员进行预先分割。 虚拟内存的另一个重要意义是它定义了一个连续的虚拟地址空间,并且把内存扩展到硬盘空间。 目前,大多数操作系统都使用了虚拟内存,如Windows的“虚拟内存”、Linux的“交换空间”等。
随着虚拟存储器(virtual memory)技术逐渐发展和使用,在实践中逐渐总结提出了硬件虚拟化技术。早期的所谓硬件虚拟化技术即利用软件对内存、硬盘等硬件做虚拟化处理,配合操作系统以达到分时复用的效果。这其中的代表就是IBM的System/360, 它不仅提供了新型的操作系统,还实现了基于全硬件虚拟化(Full Hardware Virtualization)的虚拟机解决方案。 这其中就包括页式虚拟内存(4k 分页虚拟存储系统)、虚拟磁盘以及 TSS 分时系统。System/360 最多可提供14个虚拟机,每个虚拟机具有 256k 固定虚拟内存。 随着时间发展,内存被操作系统抽象出来,作为地址空间进行统一管理,按需分配给应用程序使用。这样作为内存的硬件细节被操作系统隐藏了,程序只需关心地址空间就可以。 同时操作系统引入了虚拟化技术,可以对内存进行"扩容",本质是对内存的分时复用,让每个程序认为自己独占了整个地址空间。但是这样做效率并不高,因为操作系统需要不断地做内存搬运(这一点与ovelay一样,本质上还是以时间换空间),并且操作系统还要为内存的管理算法,付出许多额外的计算。
内存管理方法是存储技术的基础。从内存管理角度看,主要划分为两个阶段。一、在DOS时期使用 连续物理内存分配。1.1、在早期,采用的是单一连续内存管理。内存被分成两个区域,一个是系统区域,仅供操作系统使用,可以驻留在内存的低地址部分,也可以驻留在高地址部分;另一个是用户区,它是除系统区以外的全部内存区域,这部分区域是提供给用户使用的区域,任何时刻主存储器中最多只有一个作业。所以,单一连续区存储管理只适用于单用户的情况。cpu要么处于运行状态、要么处于空闲状态。为了提高cpu的利用率,迫切需要支持多作业并发,因此又提出了分区式存储管理。该方式支持多个程序并发执行,引入了分区式存储管理。分区式存储管理是把内存分为一些大小相等或不等的分区,操作系统占用其中一个分区,其余的分区由应用程序使用,每个应用程序占用一个或几个分区。分区式存储管理虽然可以支持并发,但难以进行内存分区的共享。分区式管理被分为了固定分配和动态分配。固定式分区的特点是把内存划分为若干个固定大小的连续分区。易产生内部碎片。动态分区可以在装入时按其要求进行动态分配,但是易于产生外部碎片,常用的算法有最佳、最坏、最先适配法。这个时期,需要 运行规模比较大的程序作业时,除了选择硬件资源更大的机器之外,可采用的软件层面的技术就是ovelay技术。而且由于是基于物理地址运行,所有程序分段设计的逻辑非常复杂。这一点可以参考ARM M3的加载域、运行域的实现原理。二、逐渐发展的 离散逻辑内存分配物理内存分配有一个比较明显的遗憾,那就是物理地址空间是固定的,在这个前提下,即使支持多作业并发,那每个作业占用的内存空间都是有限的。为了应对程序规模越来越大的现实问题,逐渐发展处理虚拟内存的相关技术。首先,程序不再直接基于物理地址运行,而是提出可逻辑地址的概念。通过 转换单元,可以将虚拟地址转换为物理地址,如此以来,在程序的可以不再感知物理地的存在,即使其实际占用的多块内存是不连续的,都可以将内存空间视为一个连续的整体。另外,实现物理地址与虚拟地址转换的前提基础是如何实现内存管理(即如何分配和管理)。因此,基于ovelay技术思想逐渐演化而来的一种离散的内存分配方案。这其中主要有三种实现方式:页式、段式和段页式。页式管理的基本思想是将主存划分为大小相等的若干个页面并建立页表,根据需要,作业可以分割成若干个页