目录
第三章(下)来了~觉得还不错的小伙伴可以点赞收藏关注一下,持续更新ing
3.4 外部存储器
外部存储器作为计算机的 “大仓库”,用于长期存储大量的数据和程序,弥补了主存容量的不足。主要的外部存储器包括磁盘存储器和固态硬盘。
3.4.1 磁盘存储器
磁盘存储器 (magnetic disk storage) 是一种利用磁记录技术在涂有磁记录介质的旋转圆盘上进行数据存储的辅助存储器。它就像是一个巨大的图书馆书架,不同的磁道和扇区如同书架上的不同位置,用于存放数据。磁盘存储器具有存储容量大、数据传输率高、存储数据可长期保存等特点。在计算机系统中,常用于存放操作系统、程序和数据,是主存储器的扩充。
磁盘存储器通常由磁盘、磁盘驱动器 (或称磁盘机) 和磁盘控制器构成。磁盘两面涂有可磁化介质的平面圆片,数据按闭合同心圆轨道记录在磁性介质上,这种同心圆轨道称磁道。其主要技术参数记录密度包括位密度、道密度和面密度。位密度指盘片同心圆轨道上单位长度上记录多少位单元,用位 / 毫米 (bpmm) 表示;道密度是指记录面径向每单位长度上所能容纳的磁道数,常用道 / 毫米 (tpmm) 表示;面密度是指记录面上单位面积所记录的位单元,常用位 / 毫米 ² 表示。磁盘的存储容量是磁盘上所能记录二进制数码的总量,常用千字节 (KB) 或兆字节 (MB) 来表示。存取时间包括磁头从一道移到另一道所需的时间、磁头移动后的稳时间、盘片旋转等待时间、磁头加载时间,常用毫秒 (ms) 表示。误码率指在向设备写入一批数据并回读后,所检出的错误位数与这一批数据总位数的比值。
例如,一个普通的机械硬盘,可能有 500GB 甚至 1TB 的存储容量,其转速常见的有 5400 转 / 分钟或 7200 转 / 分钟,转速影响着数据的读取速度。在读取数据时,磁头需要寻找到对应的磁道和扇区,这个过程就涉及到前面提到的存取时间等参数。
3.4.2 固态硬盘
固态硬盘(Solid State Drive,简称 SSD),是一种基于闪存技术的存储设备,它没有传统机械硬盘的旋转部件,数据存储在闪存芯片中。相比磁盘存储器,固态硬盘具有读写速度快、抗震性强、能耗低、无噪音等优势,就像是一个高效的智能仓库,能够快速地响应数据的存取请求。
以常见的 SATA 接口固态硬盘为例,其连续读取速度可达 500MB/s 以上,而连续写入速度也能达到 400MB/s 左右,远远超过普通机械硬盘。而采用 NVMe 协议的 M.2 接口固态硬盘,性能更为强劲,连续读取速度甚至可以突破 3000MB/s。比如三星的 980 PRO NVMe M.2 固态硬盘,在高性能 PC 或笔记本电脑中被广泛使用,极大地提升了系统的启动速度和软件的加载速度,让用户能够快速进入工作或娱乐状态。
3.5 高速缓冲存储器
高速缓冲存储器(Cache)宛如一座桥梁,搭建在 CPU 与主存之间,是一块高速且小容量的存储器。其诞生的核心目的在于化解 CPU 与主存速度不匹配的矛盾,类比图书馆设置的热门书籍专区,方便读者快速获取高频使用资料,Cache 能够让 CPU 迅速访问常用数据与指令,提升计算机整体运行效率。
3.5.1 程序访问的局部性原理
程序访问的局部性原理是 Cache 得以存在并高效运作的理论根基。该原理表明,CPU 在访问存储器时,无论是指令读取还是数据存取,所涉及的存储单元往往集中在一个相对较小的连续区域内。具体而言,可细分为三种不同类型的局部性:
- 时间局部性(Temporal Locality):若一个信息项此刻正被访问,那么在不久的将来,它极有可能再次被访问。以程序中的循环结构为例,循环体内的指令和数据会在每次循环时反复被调用,这便是时间局部性的典型体现。比如一段计算 1 到 100 累加和的循环代码,每次循环都会访问累加变量和循环控制变量,这些变量在短时间内会被多次访问。
- 空间局部性(Spatial Locality):在即将到来的时刻要使用的信息,大概率与当前正在使用的信息在空间地址上紧密相邻。例如,数组在内存中以连续存储的方式存放,当程序访问数组中的某个元素时,其周边相邻的元素也极有可能在后续操作中被访问。假设存在一个存储学生成绩的数组,当程序读取某个学生的成绩时,很可能紧接着会读取该学生相邻位置的其他信息,如姓名、学号等。
- 顺序局部性(Order Locality):在常见程序中,除转移类指令外,绝大多数指令遵循顺序执行原则。据统计,顺序执行与非顺序执行指令的比例大致为 5:1。此外,对大型数组的访问通常也是顺序进行的。指令的顺序执行特性以及数组的连续存放方式,共同构成了顺序局部性产生的根源。例如,一段顺序执行的代码,从初始化变量、执行计算操作到输出结果,指令依次按顺序执行,体现了顺序局部性。
3.5.2 Cache 的基本工作原理
当 CPU 产生数据访问需求时,会率先在 Cache 中展开查找。若所需数据恰好存在于 Cache 中(此情况称为命中),CPU 可直接从 Cache 中快速读取数据,速度极快,极大提升了数据访问效率;若数据未在 Cache 中(即未命中),CPU 则需从主存中读取数据,与此同时,会将该数据所在的主存块一并调入 Cache 内,以便后续可能再次访问该数据时能够直接从 Cache 获取,减少访问延迟。
例如,当 CPU 执行一段循环程序,反复访问数组中的元素时,初次访问数组元素可能会出现未命中的情况,此时数据从主存读取并存储到 Cache 中。后续再次访问相同数组元素时,基于时间局部性原理,这些元素大概率已存在于 Cache 内,CPU 便能实现快速命中读取,大大加快了程序运行速度。假设循环程序需要对一个包含 1000 个元素的数组进行多次累加操作,首次访问数组元素时,可能由于 Cache 中无对应数据,需从主存读取,耗时较长。但随着循环推进,数组元素被陆续存入 Cache,后续访问便能快速命中,显著提升了累加操作的整体效率。
3.5.3 Cache 和主存的映射方式
Cache 与主存之间存在多种映射方式,常见的有直接映射、全相联映射和组相联映射,不同映射方式各有优劣,适用于不同场景:
- 直接映射:在直接映射机制下,主存中的每一个块仅能映射到 Cache 的一个特定位置。具体实现方式通常为,主存块号对 Cache 块数取模,所得结果即为该主存块在 Cache 中的映射位置。这种映射方式简单直接,易于硬件实现,但缺点是冲突率较高。举例来说,假设有一个 8 块的 Cache 和 32 块的主存,当主存块号为 0、8、16、24 的块都试图映射到 Cache 的第 0 块位置时,就会引发冲突,导致频繁替换,降低 Cache 的命中率。
- 全相联映射:全相联映射赋予了主存块极高的映射灵活性,主存中的任意一个块均可映射到 Cache 中的任意位置。该方式冲突率极低,能够最大程度提升 Cache 的命中率,但实现过程极为复杂,硬件成本高昂。因为在数据查找时,需要对 Cache 中的每一个块逐一进行比较判断是否命中,这对硬件电路的设计与性能提出了极高要求。例如,在一个具有 64 块的 Cache 中,若采用全相联映射,当 CPU 访问某个主存块时,硬件需要对 Cache 中的 64 个块依次检查,判断是否存在匹配项,这无疑增加了硬件设计的复杂度与成本。
- 组相联映射:组相联映射巧妙融合了直接映射和全相联映射的优势。它将 Cache 划分为若干组,主存块映射到 Cache 的组是预先确定的,但在组内的块位置则是任意的。以将 Cache 分为 8 组为例,主存块依据其块号映射到对应的组,随后在组内采用全相联映射方式进行查找。这种映射方式在性能与复杂度之间找到了良好的平衡点,既具备一定的映射灵活性,降低了冲突率,又在硬件实现上相对可行,成本可控。例如,当主存块号为 10 的块,根据映射规则被映射到 Cache 的第 2 组,在第 2 组内,通过全相联映射查找是否存在该块,相较于全相联映射对整个 Cache 进行查找,大大减少了比较次数,同时又比直接映射的冲突率低。
3.5.4 Cache 中主存块的替换算法
当 Cache 存储空间已满,却又需要调入新的主存块时,就必须执行替换操作,以腾出空间存放新数据。常见的替换算法有以下几种:
- 随机算法(Random,RAND):随机算法是最为简单直接的替换策略,它随机选择一个 Cache 块进行替换。这种算法虽然实现容易,但由于未充分考量程序访问的局部性特点,在实际应用中,替换效果往往差强人意,可能会导致频繁替换有用数据,降低 Cache 的命中率。例如,在一个频繁访问特定区域数据的程序运行过程中,随机算法可能会随机替换掉恰好是后续即将访问的数据块,从而增加未命中次数。
- 先进先出算法(First In First Out,FIFO):先进先出算法遵循先进入 Cache 的块先被替换的原则。该算法实现难度低,但存在明显缺陷,它仅仅依据块进入 Cache 的先后顺序进行替换,而不区分块的使用频率,可能会误将一些频繁使用的块替换出去。比如,在一个循环程序中,早期进入 Cache 的一些块虽然是最先进入的,但在循环过程中被频繁访问,FIFO 算法可能会将这些块替换掉,影响程序运行效率。
- 最近最少使用算法(Least Recently Used,LRU):最近最少使用算法充分利用了程序访问的局部性原理,它选择在最近一段时间内使用频率最低的 Cache 块进行替换。在多任务处理系统中,当 Cache 空间不足时,LRU 算法能够精准识别出那些长时间未被访问的程序或数据块,优先将其替换,因为这些块在近期再次被访问的概率相对较低。例如,在同时运行多个应用程序的计算机系统中,某些应用程序在后台长时间未被操作,其相关数据块在 Cache 中长时间未被访问,LRU 算法会优先替换这些块,为正在前台运行的活跃应用程序腾出空间,保障系统整体性能。
3.5.5 Cache 的一致性问题
在多处理器系统架构下,由于多个处理器各自配备独立的 Cache,当其中一个处理器对其 Cache 中的数据执行修改操作后,其他处理器的 Cache 中若仍保留该数据的旧副本,就会引发 Cache 的一致性问题,导致数据不一致,影响系统正常运行。为有效解决这一棘手问题,业界通常采用以下几种方法:
- 写直达(Write Through):写直达策略要求当 CPU 对 Cache 执行写操作时,同步将数据写入主存以及其他处理器的 Cache 中,以此确保各处理器 Cache 以及主存中数据的一致性。然而,这种方法的弊端在于,每次写操作都需同时向多个位置写入数据,无疑大大增加了写操作的时间开销,在一定程度上影响了系统的整体性能。例如,在一个多处理器协同工作的服务器系统中,若频繁进行写操作,写直达策略会使系统在数据写入环节耗费大量时间,降低数据处理效率。
- 写回(Write Back):写回策略采取更为灵活的方式,当 CPU 对 Cache 进行写操作时,仅修改 Cache 中的数据,并不会立即将数据写入主存。只有当该 Cache 块后续因其他原因被替换时,才会将修改后的数据一次性写回主存。这种方法有效减少了写操作的执行次数,提升了系统性能,但需要额外增设标记位,用于记录 Cache 块是否被修改过,增加了硬件设计的复杂度。例如,在一个图形处理任务中,处理器会频繁对 Cache 中的图形数据进行修改,采用写回策略,可减少对主存的写入次数,加快图形处理速度,同时通过标记位记录数据修改情况,确保数据的一致性。
- 总线监听(Bus Snooping):总线监听机制依赖于每个处理器实时监听系统总线,时刻检测其他处理器对共享数据的操作。一旦检测到共享数据被修改,处理器会及时更新自身 Cache 中的数据副本。以基于共享总线的多处理器系统为例,每个处理器的 Cache 控制器如同一个 “监听者”,时刻关注总线上的写操作。当其中一个处理器修改了共享数据并将写操作信号发送到总线上时,其他处理器的 Cache 控制器捕获到该信号后,立即检查自身 Cache 中是否存在对应数据副本,若存在则进行更新,保障了各处理器 Cache 数据的一致性。
3.6 虚拟存储器
虚拟存储器是一种通过硬件和软件的结合,为用户提供一个比实际物理内存大得多的存储空间的技术,它就像是一个可以无限扩展的虚拟仓库,让用户感觉自己拥有足够大的内存空间来运行程序和存储数据。
3.6.1 虚拟存储器的基本概念
虚拟存储器赋予程序使用远超实际物理内存大小地址空间的能力,这个庞大的地址空间被称作虚拟地址空间。在程序运行过程中,操作系统肩负起将虚拟地址精准映射到实际物理地址的重任。虚拟存储器的出现,有效攻克了内存容量不足的难题,同时为程序共享提供了便利条件。例如,一台计算机实际仅配备 4GB 物理内存,但借助虚拟存储器技术,程序能够使用 8GB 甚至更大的虚拟地址空间来顺畅运行,极大拓展了程序的运行环境,满足了复杂应用程序对内存的高需求。
3.6.2 页式虚拟存储器
页式虚拟存储器将虚拟地址空间和物理地址空间统一划分为大小相等的页。虚拟地址由页号和页内偏移两部分构成,通过页表这一关键数据结构,实现虚拟页号到物理页号的映射转换。当 CPU 访问虚拟地址时,首先借助页表查找对应的物理页号,再结合页内偏移,精准定位到实际的物理地址。例如,假设页面大小设定为 4KB,一个虚拟地址表示为 0x12345678,其中高 20 位代表页号,低 12 位则是页内偏移。CPU 通过查询页表,找到页号对应的物理页号,然后将物理页号与页内偏移相结合,从而获取在物理内存中的准确地址,实现数据的准确访问。
3.6.3 段式虚拟存储器
段式虚拟存储器依据程序的逻辑功能,将程序划分为不同的段,每个段都拥有独立的段号和段内偏移。段表负责将段号映射到段在物理内存中的起始地址。与页式虚拟存储器不同,段式虚拟存储器中段的大小并非固定不变,而是根据程序的逻辑结构灵活确定。比如,一个完整的程序通常包含代码段,用于存储程序指令;数据段,用于存放程序运行过程中使用的数据;堆栈段,用于管理函数调用、局部变量等。每个段的大小根据实际需求进行合理分配,代码段的大小取决于程序代码的长度,数据段的大小则依据程序运行时所需存储的数据量而定。
3.6.4 段页式虚拟存储器
段页式虚拟存储器结合了页式和段式的优点。先将程序划分为段,再将每个段划分为页。虚拟地址由段号、页号和页内偏移组成。首先通过段表找到段对应的页表起始地址,再通过页表找到物理页号,最后结合页内偏移得到物理地址。这种方式既具有段式的逻辑清晰、便于程序共享和保护的优点,又具有页式的内存管理方便、碎片少的优点。
3.6.5 虚拟存储器与 Cache 的比较
比较维度 | 虚拟存储器 | Cache |
原理运用 | 借助程序访问的局部性原理,提升存储系统整体性能 | 基于程序访问的局部性原理,提升存储系统性能 |
地址映射 | 存在地址映射机制,将虚拟地址映射为物理地址 | 存在地址映射机制,把主存地址映射到 Cache 地址 |
替换策略 | 具备替换算法,在虚拟内存空间不足时,处理数据替换 | 拥有替换算法,用于在 Cache 空间不足时进行数据替换 |
设计目的 | 致力于解决内存容量不足的难题,让程序可使用远超物理内存的虚拟地址空间 | 主要用于解决 CPU 和主存速度不匹配的矛盾,加快 CPU 访问数据的速度 |
存储介质 | 主要依托主存(DRAM)和磁盘,主存存放当前运行的部分程序和数据,磁盘用于存储暂时不用的程序和数据 | 通常采用高速的 SRAM,因其速度快,能快速响应 CPU 的数据请求 |
地址空间 | 虚拟地址空间远大于实际物理地址空间,借助虚拟地址映射到物理地址 | 地址空间是物理地址空间的一部分,是对物理内存的高速缓存 |
管理方式 | 管理需硬件和操作系统软件协同合作,操作系统负责虚拟地址到物理地址的映射、内存分配、页面置换等 | 管理主要由硬件完成 |