01改变世界:计算机原理趣谈

978-7-115-58395-6
作者: 逸之
译者:
编辑: 张涛

图书目录:

详情

本书系统地介绍了计算机的组成与基本运行原理;从最底层的电路设计开始,层层揭秘了计算机软、硬件的实现逻辑。 本书分为5章,依次从硬件、软件、网络、编程和应用方面切入,使用通俗的语言和丰富的图解,帮助读者高效地理解计算机的知识。 本书深入浅出,既可作为高等院校计算机相关专业的参考读物,也可作为计算机相关从业人员和计算机业余爱好者的入门科普读物。

图书摘要

版权信息

书名:01改变世界:计算机原理趣谈

ISBN:978-7-115-58395-6

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

著    逸之

责任编辑 张涛

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315

内容提要

本书系统地介绍了计算机的组成与基本运行原理;从最底层的电路设计开始,层层揭秘了计算机软、硬件的实现逻辑。

本书分为5章,依次从硬件、软件、网络、编程和应用方面切入,使用通俗的语言和丰富的图解,帮助读者高效地理解计算机的知识。

本书深入浅出,既可作为高等院校计算机相关专业的参考读物,也可作为计算机相关从业人员和计算机业余爱好者的入门科普读物。

前 言

这是一本浅谈计算机原理的科普书。程序是如何运行的?图像是如何显示的?网络是如何通信的?本书回答了许多关于计算机原理的疑问,可以最大限度地满足读者对“神秘的计算机”的好奇心。

计算机是一件功能强大的工具,它的“世界”是一个精彩纷呈的“世界”。本书就如一位尽职的“导游”,带领读者游览这个充满神奇的“世界”,观赏其中的“风景和文化”。

计算机的神秘之处体现在,其运行的原理“封存”在黑盒一般的芯片和“看得见、摸不着”的软件里。当人们按下键盘上的按键,看着屏幕上显示出来的信息时,常常会思考,在计算机运行的过程中,哪些软件、硬件会以什么样的方式通力协作,同时感慨自己对眼前这台机器的一无所知。

本书不像专业图书那样深奥难懂,而是用浅显的语言和图解,把计算机的基本原理准确地表达出来,让读者了解这个“披着神秘面纱”的机器。

如果把学习计算机专业知识比作百米冲刺或马拉松,那么学习本书就相当于散步或快走。如果读者读过《01改变世界:计算机发展史趣谈》,则能更轻松地适应本书的内容风格,并对书中的一些知识点感到熟悉。下面先呈上编者精心准备的3份预备知识,帮助读者更高效地理解本书。

1.硬件与软件

计算机中所有看得见、摸得着的都是硬件,如主机箱、显示器、鼠标、键盘等。若把计算机里的某个部件拆开,里面是具有高科技含量的电路板和芯片,以及数不胜数的电阻、电容和晶体管等电子元器件。了解计算机硬件后,操作计算机就可以像操纵提线木偶一样,只要牵动一些主要关节,就能演绎出生动的木偶戏。

1945年,冯·诺依曼在《EDVAC报告书的第一份草案》中,将计算机的主体构成归纳为运算器、控制器、内部存储器(简称内存)、输入模块和输出模块(通常并称I/O[1]模块)五大部分,如图1所示。运算器和控制器组成了如今的中央处理器(CPU),它和内存一起扮演着计算机“大脑”的角色,前者负责思考,后者负责记忆。I/O模块则是协助“大脑”与外界沟通的“万能翻译官”,掌握着各种外部设备(包括输入设备和输出设备,简称外设)的“语言”,并能适应它们各不相同的“语速”。

[1] Input/Output的缩写。

图1 计算机的主体构成

这五大部分在狭义上构成了计算机的全部,但人们还是习惯把外设也视为计算机的一部分。毕竟少了外设,计算机纵有一身“本领”也无从施展。

和实实在在的硬件相比,软件则抽象得多。软件的本质是信息。早在原始社会时期,人类的祖先就开始在石头和兽骨上刻出各种符号,给绳子打上不同形状的绳结,并约定好它们的含义。这些就是最早的“软件”,古已有之,只不过现代计算机中的软件是靠电路的通断(电平的高低)来表示的。

如果说硬件是计算机的躯体,那么软件就是计算机的灵魂。如今计算机的强大,除了得益于摩尔定律下硬件的飞速发展,更离不开软件的不断更新。起初,软件直接控制着硬件的每个工作步骤,它们存在于开关、旋钮和穿孔介质上;后来,人们把一些共性的步骤提取出来,形成了一种名为操作系统的复杂软件,充当起计算机使用者的硬件“管家”。这位“管家”掌握着多种技能。

2.二进制单位

通过《01改变世界:计算机发展史趣谈》,读者了解了二进制数的基本形式和换算方法,并接触到其充满科技感的名称——比特(bit),它是二进制的最小单位。

人们平时常会听到硬盘容量1TB、内存大小8GB、下载速度2MB[2]、文档大小300KB之类的说法,这个B代表的是字节(byte),1字节由8比特构成。比特太小了,计算机往往以字节为单位处理数据。专业上以1024倍为跨度,设置千字节、兆字节等二进制单位,如表1所示。

[2] 准确地说是2MB/s。

表1 二进制单位

单位

中文名

换算关系

B

字节

1B = 8bit

KiB

千字节

1KiB = 1024B

MiB

兆字节

1MiB = 1024KiB

GiB

吉字节

1GiB = 1024MiB

TiB

太字节

1TiB = 1024GiB

PiB

拍字节

1PiB = 1024TiB

EiB

艾字节

1EiB = 1024PiB

ZiB

泽字节

1ZiB = 1024EiB

YiB

尧字节

1YiB = 1024ZiB

注:实际使用中,一些单位中的字母i往往被省略。

3.十六进制

二进制的表示形式对人类不太友好,人们既难以直接理解其数值,又难以在脑海中快速演绎它和十进制之间的转换。研究表明,人们习惯用4比特为一组的十六进制代替二进制数,因为其形式上更为简约。如表2所示,十六进制的数使用0~9、A~F十六个符号表示,其中,A~F依次表示10~15,前缀“0x”用于标明这是个十六进制数。

表2 十六进制数示例

十进制数

十六进制形式

0

0x00

1

0x01

2

0x02

3

0x03

4

0x04

5

0x05

6

0x06

7

0x07

8

0x08

9

0x09

10

0x0A

11

0x0B

12

0x0C

13

0x0D

14

0x0E

15

0x0F

16

0x10

42

0x2A

75

0x4B

140

0x8C

初次接触二进制和十六进制的读者也许会像编者刚入门计算机时一样有些不习惯,与其视之为阅读障碍,不如掏出纸和笔,自己尝试换算几次(二进制与十六进制之间的转换),把它变成一种阅读乐趣吧。

注:书中有些术语的英文名称引自维基百科。

编者

第1章 硬件篇

1.1 CPU:一颗强大而单纯的“大脑”

通常称CPU为计算机的“大脑”。它“脑力”十足,肩负着所有软件的运行任务。它的构造很复杂,但做的事情很简单,只是不知疲倦地执行既定的指令罢了。

1.1.1 何为CPU

谈起计算机,人们常提到半导体、晶体管、集成电路、芯片、(微)处理器、CPU这样的词汇,可细细琢磨起来,却似乎总是无法明晰它们的含义,以及它们相互之间的关系。“走完”《01改变世界:计算机发展史趣谈》的旅程,想必大家已经对半导体、晶体管和集成电路有所了解。如果把晶体管比作房屋的话,那么半导体就是建造它的砖瓦。如果屋子相距太远,数据“串起门来”就不太方便了,于是出现了“居民”高度密集的“小区”——集成电路。

“小区”虽大,里头的建筑却普遍不高,整个外形呈薄片状,于是集成电路就有了芯片(Chip)这个别称。芯片的功能各不相同,大体可以分为处理器芯片和存储芯片两种。

顾名思义,处理器就是处理数据的器件。在大规模集成电路(晶体管数量上千)出现以前,处理器由印制电路板上多块分立的芯片组成,它们各有各的功能,通过印制电路板上的电路互通有无,协力完成数据处理,相当于靠“公路网”连通着的若干个“小区”。

大规模集成技术成熟后,这些不同功能的电路就被集成进了同一块芯片中,相当于将几个“小区”建在一起,处理器的体积和功耗大大缩小,成了微处理器(Microprocessor)。如今,处理器和微处理器基本上是两个等价的名词了。

随着计算机硬件的复杂化,衍生出了各种功能的处理器,其中最核心、最强大的那一块就是中央处理器(Central Processing Unit,CPU)。其他最典型的处理器就是图形处理器(Graphics Processing Unit,GPU),其专门处理图形显示方面的数据,是为CPU分忧解难的“大功臣”。

后来,人们又将多组处理器电路集成到单个芯片上,打造出多核处理器(Multi-core Processor),每组处理器电路就是一个内核,赋予了计算机“一芯多用”的并行处理能力。

1.1.2 万能的指令

CPU是计算机的“指挥中心”,计算机的每一个“动作”都服从“指挥中心”的安排。不过CPU没有自主意识,它的工作其实非常机械、简单,无非是不知疲倦地循环获取、理解和执行指令(Instruction)。这些指令来自内存,但内存当然不是CPU的“上司”,它更像一份备忘录或日程表,上面记录着一条条需要执行的指令(也就是人们常说的程序)。内存中的指令加载自外存,而外存中的指令是通过I/O模块事先输入进去的(编程),其源头最终指向计算机的使用者——人类。人才是CPU真正的“上司”,如图1.1所示。

图1.1 CPU指令溯源

人们把某个CPU支持的所有指令的合集称为指令集(Instruction Set),数据类型、寄存器数量和种类、内存管理方式等计算机的核心设计都围绕指令集展开,这些内容搭建了计算机的整体框架,统称为指令集架构(Instruction Set Architecture,ISA),简称架构。人们谈论CPU时常说的x86、ARM就是指不同的CPU架构。

以公司职员为例,假设某位职员具备数据整理、统计分析、邮件收发、总结汇报等基本技能。老板可能会对他下达这样的任务:汇总本周的经营数据,整理成表后与上周情况进行对比;将分析结果群发给各部门经理,收齐他们的反馈意见,形成周报后发给老板。

这项任务可以拆分成如表1.1所示的一系列指令,每条指令都是对职员技能的调用。如果将这4项技能用计算机的语言编号(00数据整理、01统计分析、10邮件收发、11总结汇报),那么整个任务的指令代码(简称指令码)序列就是00 01 10 10 11 10。

表1.1 公司职员的任务分解

步骤

指令

调用技能

操作对象

目标对象

1

汇总本周的经营数据,整理成表

数据整理

本周数据

汇总表

2

与上周情况进行对比

统计分析

上周数据

分析结果

3

将分析结果群发给各部门经理

邮件收发

分析结果

各部门经理

4

收齐部门经理的反馈意见

邮件收发

反馈意见

5

将分析结果和反馈意见形成周报

总结汇报

分析结果、反馈意见

周报

6

将周报发给老板

邮件收发

周报

老板

不过,单单标识技能项的指令是不完整的,职员还需要知道该对谁、对什么事物施展这些技能。不妨把表中的施展对象也一一编号:000本周数据、001汇总表、010上周数据、011分析结果、100各部门经理、101反馈意见、110周报、111老板。那么这项任务的完整指令码序列就有了,具体如下:

00 000 001
01 010 011
10 011 100
10 101
11 011 101 110
10 110 111

如果读者对《01改变世界:计算机发展史趣谈》中讲解的穿孔纸带上的程序还有印象,那一定对上述指令格式并不陌生。指令码中,标识技能的部分称为操作码(Operation Code),标识作用对象的部分称为地址码(Address Code)。单条指令中,操作码有且仅有一个,但地址码可以没有或多个。

地址码可以是待处理的操作数(Operand)[1]本身,但更多情况下,它标识着操作数的地址,操作数存在于内存,或者CPU中一种名为寄存器(Register)的容器中。内存被人为划分成一块块小区域,相当于一个个小抽屉,每个“抽屉”都有自己独有的编号,即内存地址。每个寄存器也有自己独有的编号,即寄存器地址。

[1] 也称运算数,指处理或运算的对象。引入这一概念,是因为“数据”过于宽泛,操作数、地址、指令等都是数据。

一个内存“抽屉”或一个寄存器可以存储一个操作数或一条指令(包括操作码和地址码),在冯•诺依曼体系结构中指令也是一种数据。

仔细琢磨,寄存器其实古已有之,算盘中的档、机械计算器中的齿轮、机电计算器中的继电器,都发挥着临时存储的作用,只不过它们还肩负着运算的使命,那时的运算器和寄存器尚未严格分离。

1.1.3 CPU是如何执行指令的

接下来,让大家通过一个最基本的例子管窥一下CPU大致的工作流程:

1+2=3

1.准备工作

加数1和2分别存储于内存的两个“抽屉”中,预期把相加的结果存入紧挨着它们的“抽屉”。图1.2为包含16个“抽屉”的内存示例,假设加数分别存储于8号和9号“抽屉”,10号“抽屉”用于存储结果,没有用到的“抽屉”中内容默认为0(图中标为浅灰色)。

图1.2 数据在内存中的存储示例

整个运算过程需要用到如表1.2所示的4种指令。

表1.2 示例所需指令列表

指令

操作码

描述

LOAD

00

加载指令,从内存中取数据到寄存器

ADD

01

相加指令,将寄存器中的数相加

STORE

10

存储指令,将寄存器中的数据存入内存

HALT

11

停机指令,表示程序结束

此外,人们还需要两个数据寄存器(Data Register,DR)用于暂存两个加数,其中一个DR还将用于暂存结果,这种设计可大大节省寄存器的开支。不妨将这两个寄存器称为DRA和DRB,地址分别编码为01和10。

至此,可以列出实现相加运算的所有步骤,也就是完整的程序了,如表1.3所示。

表1.3 示例程序[2]

步骤

指令

指令码

描述

1

LOAD DRA M(8)

00 01 1000

将内存1000处的数据加载到01号寄存器DRA

2

LOAD DRB M(9)

00 10 1001

将内存1001处的数据加载到10号寄存器DRB

3

ADD DRA DRB

01 01 10

将DRA和DRB中的数相加,结果存入DRA

4

STORE DRA M(10)

10 01 1010

将DRA中的数据存入内存1010处

5

HALT

11

程序结束

[2] 用M(x)表示第x号内存“抽屉”。

现在,将这段包含5条指令的程序放在内存的0~4号“抽屉”,如图1.3所示。由于地址码的长度和数量不一,指令码显得参差不齐,因此对不足8位的指令码进行补零。

2.过程解析

这段程序的运行由控制器和运算器协作完成,前者“对付”指令,后者“专攻”运算。除了前面提到的DR,它们还需用到几个特殊的寄存器,才能顺利开展工作。

1)程序计数器(Program Counter,PC),保存当前需要执行的指令所在的内存地址,默认情况下,每当从内存中取出这条指令,PC就进行自增,更新为下一条指令的内存地址。

图1.3 指令在内存中的存储示例

2)指令寄存器(Instruction Register,IR),保存从内存中获取的指令。

3)内存地址寄存器(Memory Address Register,MAR),保存CPU需要读写的内存地址。

4)内存数据存储器(Memory Data Register,MDR),保存从内存获取的数据或准备写入内存的数据。

5)程序状态字(Program Status Word,PSW)寄存器,保存一系列“是否”信息,用于标识CPU控制和运算过程中的各种状态,如是否允许中断(允许打断当前任务),运算结果是否为零、是否为负值、是否溢出(值太大存不下)等。

控制器、运算器和这些寄存器之间的数据流关系大致如图1.4所示,初看有点不明所以,没关系,在看完程序的整个运行过程后就一目了然了。

图1.4 数据流关系

大体上,可以把指令的处理过程切分为获取、解析和执行3个阶段。下面从第一条指令LOAD DRA M(8)开始,分析CPU在每个阶段的工作。

指令获取阶段:将指令从内存中读取至IR。如图1.5所示,PC的初始值为0000 0000,该值被传入MAR,控制器根据MAR将0号“抽屉”中的指令0001 1000取出,存入MDR,顺势再存入IR,PC自增,更新为0000 0001。

图1.5 LOAD DRA M(8)取指令阶段数据流图与流程图

指令解析阶段:识别操作码和地址码。本例中,操作码只有两位,因此控制器将识别IR中的前两比特。不同的操作码将激活不同的电路完成下一阶段的工作,这一选择可以用与门和非门的简单组合来实现,如图1.6所示。

地址码除了数量不定,种类也很多,它既可以是操作数,也可以是寄存器地址或内存地址,而在这个地址所指的位置,可能存放着操作数,也可能存放着另一个地址。控制器需要把这些不同的地址码区分开。

图1.6 操作码解析电路

指令执行阶段:由运算器进行运算,必要时读写内存。如图1.7所示,控制器将地址码1000传入MAR,而后根据MAR将8号“抽屉”中的操作数0000 0001取出,存入MDR,顺势再存入DRA。

至此,第一条指令执行完毕,DRA获取到操作后的值。以同样的过程执行第二条指令LOAD DRB M(9),DRB也可以获取到操作后的值。

图1.7 LOAD DRA M(8)执行指令阶段数据流图与流程图

由于针对每条指令,CPU在前两个阶段总是做着同样的事情,到第三阶段才开始做出不同处理,因此下面省去了一些重复描述,仅讨论指令的后续执行阶段。

到了第三条指令ADD DRA DRB,如图1.8所示,控制器发现需要运算,于是激活运算器,把DR中的操作数传给它。由于运算器可以完成各种算术和逻辑运算,控制器还需要指定运算类型——加法。运算器在完成运算后将结果交还给控制器,控制器转而存入DRA。此外,运算器还将更新PSW,由于此次运算结果不为负值,不为零,也没有溢出,因此将PSW中相应的3比特置0。至于是哪3比特,暂且不用关注。

图1.8 ADD DRA DRB指令执行阶段数据流图

第四条指令STORE DRA M(10)的执行过程是LOAD指令的反演,如图1.9所示,控制器将地址码1010传入MAR,将DRA中的待写数据传入MDR,而后根据MAR将MDR中的数据存入10号“抽屉”。

第五条指令HALT仅告知控制器一段程序终结了,毕竟内存是连续的,如果没有HALT,CPU将尝试处理毫无意义的0000 0000或乱码,后果不堪设想。

3.更高级的程序控制

上例中的程序是相对简单的顺序结构,每加载一条指令,PC总是自动更新为下一个“抽屉”的地址。其实程序往往是复杂的,其运行很少会像乘坐地铁或火车那样顺序地从第一站走到最后一站,而是更像走一个包含分支、循环等岔路的迷宫。PC的值时不时就会被跳转指令改写。

图1.9 STORE DRA M(10)执行指令阶段数据流图与流程图

于是,CPU可能需要跳过若干指令而直接执行它们之后的指令,或者返回到前面已经执行过的某条指令,再执行一遍。当然也可能在判断PSW中的某个状态后决定不跳转,又或者临时进入另一个任务,执行完后再返回,这就需要CPU用寄存器记住跳转前的位置。几种常见的程序流程如图1.10所示。

图1.10 几种常见的程序流程

这样看来,CPU除了“埋头苦干”,还得“眼观六路,耳听八方”。

程序控制中还有值得一提的概念——中断,是否允许中断由专门的中断开关指令决定。想象一位领导,正在办公室赶着一份明天要用的报告,却时不时被秘书急促的敲门声给打断,这次是某个员工转岗要签字,下次是某个工会活动要审批。CPU就像这位领导,工作很忙,但使用者还是喜欢时不时地打断它,比如点一下鼠标,敲一下键盘,这些操作都会向CPU发送一个中断信号,CPU收到中断信号后往往不得不停下手中的“活”,优先处理这些事件,要是稍有怠慢,使用者会觉得“很卡”。而当PSW中相应的中断标志呈现禁用状态时,便相当于在领导办公室的门上挂出了“勿扰”的牌子,此时CPU便可以专心致志地做完手头的工作了。

4.指令的流水线技术

经过上面的描述,大家已经对CPU的运作过程有了最基本的了解,它按部就班地读取着指令,并依次解析、执行它们。其整个过程井然有序,足以应对人类交托的所有任务。唯一美中不足的是,资源没有得到充分利用,速度还有提升空间。当大家将CPU中的电路切分为3个模块,它们分别负责指令的获取、解析和执行,就会发现,任意时刻都只有一个模块在工作,而另两个模块在等待着。其效率非常糟糕。假设指令处理的3个阶段耗时相等,都为1个单位时间,那么单条指令就需要3个单位时间去完成,如图1.11所示。

图1.11 非流水线指令序列处理过程

这就好比某家装配厂雇佣了3名员工,分别负责组装、测试和包装,老板期待着他们高效协同,结果却总有两个人闲着。大家都知道现实中的工厂是不可能这么做的,而是采用流水线(Pipelining)的模式让每个员工都忙起来。CPU的设计者也意识到了这一点:当解析模块获取到指令之后,获取模块完全没有必要等着,它可以马上去取下一条指令;当执行模块开工之后,解析模块可以解析下一条指令,而获取模块可以去取下一条指令,如图1.12所示。这样一来,平均每条指令的处理就只需要1个单位时间,效率是之前的3倍。

图1.12 流水线指令序列处理过程

事实上,上面对指令处理的阶段划分过于粗糙,取指令的一次内存访问需要消耗不少时间,而指令的解析可以很快完成,到了执行阶段,不同任务的耗时更是千差万别。3个阶段耗时不等,出于木桶效应,上述的单位时间要取它们中最长的那一个,最终,相互等待的情况还是十分严重。为此,CPU的设计者们将指令的处理切分成更多小阶段,形成了超流水线(Superpipelining)技术,如图1.13所示。

图1.13 超流水线指令序列处理过程

这些小阶段的个数被称为流水线的级数,英特尔在1978年推出的8086和8088处理器只有2级,随后不断增加级数,到2004年的Pentium 4处理器已有31级。但由于流水线的实现需要在级与级之间增设临时存放阶段处理结果的寄存器,级数过深后,这些额外的存取操作反而会拖累CPU的整体效率。计算机的设计真是一种权衡的艺术,意识到问题的英特尔很快对产品进行“降级”,把之后的处理器流水线级数稳定在14~20。

超流水线技术对应到工厂中,相当于雇佣了更多员工,每个员工做更简单的事,但重复的次数增加了,整体产能也上去了。但工厂的老板可能还是不满意,他准备复制现有模式,增加流水线,使产能进一步翻番。这就是CPU中的超标量(Superscalar)技术。通过增加相同的处理电路,可以实现2条,乃至多条指令的同时处理,如图1.14所示。

图1.14 超标量流水线指令序列处理过程

1.1.4 另类的哈佛结构

在冯•诺依曼体系结构中,指令和数据被一视同仁,它们共享着同一组AR和DR,像一条单车道的公路,指令和数据只能一个挨着一个通过。其实也有将指令和数据严格区分的做法,那就是比较少见的哈佛结构。哈佛结构得名于《01改变世界:计算机发展史趣谈》中讲到的Harvard Mark I,虽然这台机电计算机还没有存储程序的设计,但它分别为指令和数据设计了独立的通道,如图1.15所示。哈佛结构拥有独立的指令内存和数据内存,并设置了两组AR和DR分别与其通信,这种“双车道”的设计允许CPU在同一时间访问指令和数据,以获得更高的运行效率,但代价是提高了硬件成本和设计成本,并损失了软件层面的灵活性。

图1.15 哈佛结构

1.2 内存和它的小伙伴们:解剖计算机的记忆

20世纪40年代初,ABC的发明者阿塔纳索夫首次用表示人类记忆的单词memory称呼计算机中的存储器,这一名词沿用至今,常指内存。如今的计算机有着更复杂的存储系统,以满足短期或长期的“记忆”“速记”和“慢记”等需求。除了1.1节中提到的内存和寄存器,计算机中还有许多“各怀绝技”的存储器,它们将在本节中一一登场。

1.2.1 存储的金字塔结构

计算机的运行,是一场声势浩荡的数据迁徙。“比特们”以字节(byte)为一组,以成千(KiB)上兆(MiB)之流,汇吉(GiB)太(TiB)之汪洋。它们随着周期性的电压起伏,排着队从某个存储器中“泵出”,经过主板上“阡陌纵横”的电路,注入另一个存储器。

计算机运行时,操作系统从外存“苏醒”,“进驻”内存开始工作,它“指挥”着CPU从外存获取需要的数据,“途经”内存,有时也“路过”缓存(Cache),抵达寄存器进行处理,并让结果沿原路返回至外存,如图1.16所示。

图1.16 数据的“旅程”

CPU中的缓存常被称为高速缓存,不同于容量只有一个内存“抽屉”的寄存器,它能容下许多“抽屉”的内容。有了缓存,CPU可以成片成片地从内存中读写数据,由于在存储空间上,下一条要处理的数据往往与上一条是紧挨着的,这种做法可以大大加快CPU与内存之间数据交换速度。

数据的“旅程”之所以这么“坎坷”,原因在于CPU的速度太快,唯一能跟上它的寄存器又价格高昂、容量小,而成本更低的存储器可以提供更大的容量,但它们的速度又一个比一个慢。这是权衡速度、成本和容量的结果。

由此,计算机中的存储体系出现了森严的等级制度,内存和它的上下级们形成了如图1.17所示的金字塔结构。越靠近塔顶的存储器读写速度越快,相应的,制造成本也越高;越靠近塔底的存储器读写速度越慢,但容量也越大。最底层的存储器包括用于海量数据备份的磁带,以及方便移动的U盘、移动硬盘、光盘等,它们的共同特征是长期脱离计算机,仅在需要时接入计算机,因而被人们称为离线存储器。

图1.17 存储的金字塔结构

如果把数据比作食材,CPU中控制器和运算器就是“大厨”,寄存器是“锅”,缓存是摆在灶台上的“餐盘”,内存是搁在水池边的“篮子”,外存是家里的“冰箱”,离线存储器就是“菜市场”。

目前,在这一金字塔中,内存及以上的存储器为速度牺牲了自持数据的能力,数据只临时存在于它们身上,一旦断电就“灰飞烟灭”,因而又被称为易失性存储器;而内存以下的存储器是非易失的,保持数据不依赖于外部供电。

1.2.2 具有记忆力的电路

尽管人们所熟悉的组合逻辑电路不仅可以表达二进制信息,而且通过一定的方式相连之后还能实现各种运算,但不能保存中间结果以备下次运算时使用。这种电路是“直肠子”,只能一次性把需要的运算全做完,然后直接显示出来。为此,计算机的设计者需要预见所有计算任务的全过程并把它们“焊死”在电路中,这种做法只可能出现在最早期的专用计算机中。

于是就有了时序逻辑电路——一种输出不仅取决于输入,还取决于自身状态的“神奇”电路。1918年,英国物理学家威廉•埃克尔斯和F•W•乔丹首次用电子管搭建了一种时序逻辑电路,成功将转瞬即逝的电信号留住。

接下来尝试用逻辑门构建一个该电路的示例。

编者想起ENIAC之父埃克特设计的水银延迟线,信号被“囚禁”在电、声混合的环路中,不停地循环奔跑。那么,将信号“囚禁”在回环的逻辑电路中会是什么样子的呢?

接下来,先拿一个简单的或门做实验,把它的输出端和某个输入端相连,如图1.18所示,输入端记为AB,输出端记为QBQ相连。

图1.18 首尾相连的或门

1)一开始,AB同时为0,0和0的逻辑或为0,Q便为0,BQ一致,3端都保持在0的状态,相安无事。

2)此时,如果从A端输入1,B端还为0,1和0的逻辑或为1,Q便为1,这个1反馈到B端,B也变成了1,1和1的逻辑或还是1,三端便都稳定在1的状态。

3)接着,如果再将A端的输入变回0,B端保持为1,0和1的逻辑或还是1,Q保持为1。这意味着,BQ已“互相扶持”,组成了独立的“小团体”,不论A端的输入如何变化,输出永远为1。

我们成功地实现了一个能保存1的电路,它是触发型的,在A首次从0变为1时,触发了1的存储。那么0呢?用或门的“镜像”——与门试试吧!如图1.19所示。

图1.19 首尾相连的与门

1)首先,同时令AB为1,1和1的逻辑与为1,即Q为1,BQ一致,3端都保持在1的状态,相安无事。

2)此时,如果A变为0,B端为1,0和1的逻辑与为0,即Q为0,这个0反馈到B端,B也变成了0,0和0的逻辑与还是0,3端便都稳定在0的状态。

3)接着,如果再将A端的输入变回1,B端保持为0,1和0的逻辑与还是0,Q保持为0。这意味着,BQ“同归于尽”,不论A“如何努力”,输出永远为0。

这下保存0的电路也有了,它和保存1的电路一样,也是触发型的,在A端首次从1变为0时完成0的存储。

不过,人们需要的是一个既能存1又能存0的电路,得把上面两个电路组合起来,才能存储一个完整的比特,如图1.20所示。

图1.20 由与、或门组合而成的单比特存储电路

1)先分析与门,只要与门的任意输入为0,输出必定为0。因此,如果期望Q为0,只需要确保B为0即可,A的取值无所谓。当然,当Q为0后,人们也可以通过向A输入0,使或门输出0,这个0作为与门的一个输入导致Q稳定为0,B反而可以随意变动。

2)如果期望Q为1,AB都必须输入1。但Q为1后,这个1反馈到或门的输入,A的值是可以变回0的。

3)上述两步分析中有一个共同规律,那便是,当A为0、B为1时,Q保持原样。

如此,人们得到一张令人困惑的真值表,如表1.4所示。

表1.4 与、或门单比特存储电路真值表

A

B

Q

1

1

1

0或1

0

0

0

1

原值

不过仔细观察可以发现,如果想在这个电路中存储1,必须从A输入1;如果想存储0,必须从B输入0。ABQ产生作用的状态不同,这在专业上称为A为高电平有效,B为低电平有效。高电平有效更符合人们的常识,如灯泡会在开灯时亮起、关灯时熄灭;而低电平有效却等同于灯泡在关灯时亮起。

为了避免这种逻辑混淆人们的思路,必须把B端扭转为高电平有效。采用的方法就是再增加一个非门,如图1.21所示。

图1.21 由与、或、非门组合而成的单比特存储电路

如表1.5所示,真值表得到了不错的“修缮”。A为1时存储1,B为1时存储0,当然前者还需要B=0的附加条件。

表1.5 与、或、非门单比特存储电路真值表

A

B

Q

1

0

1

0或1

1

0

0

0

原值

Q的状态转换图如图1.22所示。

图1.22 与、或、非门单比特存储电路状态转换图[3]

[3] X表示0、1皆可。

在专业上,比特的置1称为置位(Set),置0称为复位(Reset)。因此,A端常被称为S端,B端则被称为R端。由于两者的变化触发着Q的变化,故整个电路称为RS触发器。

RS触发器有多种实现方式,如将两个或非门首尾相连,或者将两个与非门首尾相连,如图1.23所示。后者输入端字母上的横杠表示低电平有效。它们的真值表如表1.6和表1.7所示,感兴趣的读者不妨自己推导一下。

图1.23 基于或非门和基于与非门的RS触发器

表1.6 基于或非门的RS触发器真值表

S

R

Q

1

0

1

0

1

0

0

0

原值

表1.7 基于与非门的RS触发器真值表

Q

0

1

1

1

0

0

1

1

原值

在RS触发器的基础上,人们还搭建了各种复杂的触发器电路,它们都拥有保持原状态、等待触发的特点,成为存储比特信息的绝佳“容器”。多个触发器组合起来,就可以用于存储一条完整的数据,如8个触发器可以组成一个8位的寄存器。

1.2.3 随机存取存储器

内存有时也被称为RAM,其实这是个泛称,指随机存取存储器(Random Access Memory),准确地说,内存是RAM的一种。这里的“随机”可不是“胡乱访问”的意思,而是指可以以相同的速度定位到其中任意一块内容。RAM通常由众多存储单元(存储一比特的单元)以矩阵的形式组合而成,通过行号和列号可以定位到任何一个单元。这如同一位将军面对一个士兵方阵,他想让任何一位士兵出列,只指明某行某列即可。

与之相对应的是顺序存取存储器(Sequential Access Memory,SAM),所有内容都按序排布着,要想访问中间的某一段,就必须先跳过排在它之前的所有内容。最典型的SAM是磁带。磁盘和光盘也是一种SAM,数据以同心圆环的形式分布在其表面,对于读写头来说,这些圆环就是带状的,盘片在驱动器中飞速旋转,好让读写头能“看遍”整个圆环。

SAM的顺序存取受累于存储器中的机械运动,而纯电子的RAM则可以靠电压的高低组合(二进制表示的存储地址)直接“命中”所需要的数据。因此,存储的金字塔中,内存及以上的存储器为了追求速度,都被设计成RAM。

根据存储原理的不同,RAM分为静态随机存储器(Static Random Access Memory,SRAM)和动态随机存储器(Dynamic Random Access Memory,DRAM)。CPU的缓存和部分寄存器都是SRAM,而内存是DRAM。那么,这一“静”一“动”是什么意思呢?

1.SRAM

图1.24是某制程为180nm的SRAM芯片在扫描电子显微镜下的影像,一个个相同的存储单元整齐地排列着,每个单元都由一个黑色的横向“X”和两个白边灰色的竖向“H”组成,后者为两个相邻单元所共用。这些像染色体一样“萌萌的小家伙”其实就是MOS管。

图1.24 电子显微镜下的SRAM[4]

[4] 图片来自维基百科“Static Random Access Memory”词条。

大家在《01改变世界:计算机发展史趣谈》中了解到,NMOS是高电平有效的,即给栅极施加高电平时,源漏两极导通;给栅极施加低电平时,源漏两极阻断。而PMOS则恰恰相反,是低电平有效的。为了便于后文逻辑电路的绘制,这里引入了如图1.25所示的简单符号。

图1.25 MOS管电路符号

在逻辑电路中,既可以用电流的通断,也可以用电压的高低来表示1和0。而电路中的电流越小,功耗也就越低,因此人们更偏爱使用后者。为了减少MOS管中的电流,仙童半导体公司聪明的工程师们在1963年发明了一种将NMOS和PMOS结合使用的结构,如图1.26所示。

图1.26 CMOS结构

PMOS和NMOS的栅极相连并作为输入端A,两者的漏极相连并作为输出端Q。工作时,对PMOS的源极施加高电平,对NMOS的源极施加低电平。当A输入高电平时,PMOS阻断,NMOS导通,Q端获得NMOS源极的低电平;当A输入低电平时,NMOS阻断,PMOS导通,Q端获得PMOS源极的高电平。两个MOS管总有一者是阻断的,无法产生电流。这是一个逻辑非门,它的NMOS和PMOS的通断状态总是互补的,因而得名互补金属氧化物半导体(Complementary Metal Oxide Semiconductor),简称CMOS,是一种常用的MOS管集成工艺。

接下来继续讨论SRAM。SRAM的存储单元由6个MOS管组成,其中4个正是一对首尾相连的CMOS,它们和触发器一样,牢牢地“锁住”一比特,如图1.27(a)所示。为了避免被这看起来有些复杂的电路“绕晕”,图1.27(b)给出了其等效的逻辑电路——一对首尾相连的非门。

上侧非门(以下简称上门)的输入端和下侧非门(以下简称下门)的输出端相连,记为Q端;上门输出端和下门输入端相连,记为端。

Q端为高电平(即上门输入高电平),则上门输出低电平,即端为低电平,这个低电平又作为下门的输入,下门输出高电平,和Q端输入保持一致。此时,电路稳定在Q低的状态,存储1。反之,若Q端输入低电平,电路便稳定在Q高的状态,存储0。

按理说,对这一电路的读取只需要直接访问Q端即可,但SRAM的设计者发现由于Q端的引线相对较长,工作时会产生寄生电容,“吃掉”部分电能,拖慢信号的传递。为了加快SRAM的读取速度,人们采用了一种更复杂的做法,用上了剩下的2个NMOS,进行如图1.28所示的连接。两者的栅极接入同一根导线WL,源漏其一与Q/端相连,其二与导线BL/相连。

图1.27 SRAM存储单元的存储电路

图1.28 SRAM存储单元

Q高(存储0)为例,读取时,先将BL和置为高电平,而后将WL置为高电平,左右两个NMOS将导通。左侧NMOS导通后,BL被Q拉至低电平[5];而本来就都处于高电平,因此右侧NMOS导通后,两者也相安无事。最终就出现了BL低高的结果,两者之间的电压差被额外的感应电路所捕获。这个感应电路越灵敏,SRAM的读取速度也就越快,BL低高表示0,BL高低表示1。

[5] 理论上,也可能是Q被BL拉至高电平,但通过在设计时控制好MOS管之间的强弱关系,可以保证Q维持在低电平。

依旧以Q高状态(存储0)为例,如果想写入1,准备工作和读取时一样,而后将从高电平置为低电平。从SRAM的读取原理可知,BL没有能力将Q拉到高电平,需要通过实现。通过MOS管强弱设计,确保有能力将拉至低电位,这一低电位通过非门的相互反馈,使Q翻转为高电位,并最终得到Q低的稳定态,即存储的比特从0变成了1。

读写的原理明朗了,但WL、BL和这3根线却来得莫名其妙。其实它们分别是字线(Word Line)和位线(Bit Line)的缩写。包括SRAM在内的半导体存储器都是由存储单元以阵列的形式组合而成的,像是座位摆放得整整齐齐的考场,字线和位线就是座位间的过道,供数据通行,将每个存储单元接入实现读写功能的电路。图1.29给出了一个4行8列的SRAM存储阵列,假设机器的字长是8位,那么这个SRAM就可以存储4个字。计算机以字为单位访问数据,因此字线的作用就是从存储阵列中选中某个字,而位线则负责对这个字中的每一位进行读写。

图1.29 4行8列的SRAM存储阵列

2.DRAM

事实上,最早的SRAM问世后,人们是直接把它当内存用的。SRAM的存取速度令人十分满意,展现出包括威廉斯管和磁芯存储器等其他内存无可比拟的优势,只不过单个晶体管只能容纳1/6比特的存储密度使其成本显得异常高昂。所幸很快,东芝公司在1965年推出1比特只需1个晶体管的DRAM之后,人们就意识到用SRAM做内存是件多么“奢侈”的事。

在个人计算机的主板上,内存以一块可插拔的印制电路板的形象出现,板上挂载着几片半导体存储芯片,如图1.30所示。这块板卡虽然不及CPU昂贵,却有着不亚于CPU的重要地位,它是实现存储程序的关键,是计算机之所以成为现代计算机的标志之一。

图1.30 个人计算机主板上的内存条[6]

[6] 图片来自维基百科“Computer Data Storage”词条。

内存也称为主存,是计算机施展思维的“舞台”。不论数据从哪里来,要到哪里去,都必经这一“集散中心”。因此,除了速度,容量也是内存的关键指标之一。

DRAM的存储单元由1个NMOS和1个电容组成,电容负责存储数据,NMOS充当读写开关,相比于SRAM有着高得多的集成度。读者可能对用电容存储数据的做法有点似曾相识的感觉,因为大家已在1942年的第一台电子计算机——ABC身上见过,密密麻麻的电容分布在其滚筒状的存储器表面,由于电容无法长时间存电,滚筒以每秒一圈的速度旋转着,确保电刷与电容一一接触以实现周期性的充电。DRAM中的电容也同样需要周期性充电,即动态刷新,一如约翰•文森特•阿塔纳索夫口中那个“健忘的孩子”,在去往商店的路上一遍又一遍提醒自己记住家长所吩咐的购物清单。这使DRAM的电耗远高于SRAM,也是DRAM名称中“动态”的由来。

DRAM存储单元的电路如图1.31所示,电容下端接入低电平,当电容上端为高电平时,即表示存储1,反之表示存储0。

图1.31 DRAM存储单元的电路

DRAM中的位线工作时同样会产生寄生电容,因此它的读取也是通过压差感应实现的。读取时,位线BL置为高电平的一半,字线WL置高电平,导通NMOS,此时电容上端如果是高电平,将拉高BL上的电压,反之拉低,这一变化由相应的感应电路捕获,得到结果。这一读取过程会破坏电容电量,因此每读一次,就要将数据重写一次。

写入的过程相对简单,将BL置高电平(写1)或低电平(写0),等WL导通NMOS后即可完成对电容的充放电。

3.SDRAM

电容的充放电需要时间,并不能像触发器那样快速响应。因此在CPU看来,尽管DRAM这位“秘书”能提供所有的生产资料,但“手脚”实在是太慢了。早期的DRAM在收到CPU发来的访存指令后便开始“自顾自”地工作起来,CPU在经过“漫长”的等待后,才能在某个不确定的时刻收到回复。

这种低效的合作方式持续了近30年,CPU终于“忍无可忍”,对DRAM呵斥到:“工作要跟上我的节奏,再这样自己玩自己的,我可要换人了!”众所周知,CPU的工作被一个规律的时钟所驱动着,如果内存也能遵循这个时钟,它们之间的交互就会顺畅得多了。DRAM不敢“怠慢”,经过一番改造,把自己“升级”成了同步动态随机存储器(Synchronous Dynamic Random Access Memory,SDRAM)。SDRAM切分出更细的组成部件和工作步骤,在与CPU一致的步调下也实现了流水线技术,在一次读写完成之前,就可以处理下一次读写任务,大大提高了内存的访问效率。1992年,韩国的三星公司首次推出SDRAM芯片,从此将DRAM“赶下了”历史舞台。

SDRAM时代到来后,三星改进内存的热情很高。

通常,内存条上嵌有8块黑色的存储芯片(类似图1.30),每块芯片开着一扇单次可供8比特同时进出的大门,也就是说,时钟每“嘀嗒”一次,SDRAM内存就“泵出”或“吸纳”64位数据。当它以100MHz的频率工作时,可以提供6400Mbit/s(800MB/s)的读写速率。三星的工程师们不满于此,1992年8月,把时钟的一个嘀嗒分成了两份,让一嘀和一哒都可以传输数据,实现了速率的翻番,即双倍数据速率(Double Data Rate,DDR),这才有了今天常见的内存名称——DDR SDRAM(双倍数据速率同步动态随机存储器)。相对应的,此前的SDRAM则被称为SDR SDRAM(Single Data Rate SDRAM,即单数据速率同步动态随机存储器)。

DDR的出现使内存在保持现有工作频率的情况下也可以对外提供翻倍的数据带宽。然而这还只是开始,2001年,三星又一次实现了速率的翻番,推出了四倍数据速率的DDR3。这一突破在2005年继续重演,拥有八倍数据速率的DDR4问世。有趣的是,SDRAM的工作频率并没有在更新换代中提升多少,难怪有人会说内存是一门接口的技术。

图1.32列出了工作区间在100~400MHz的历代DDR SDRAM,每一代都有若干不同频率的规范,横杠右侧表示该规范内存的数据传输速率,如工作在200MHz的DDR4,8倍速率相当于每秒传输1600个数据,故以DDR4-1600命名。因每个数据包含64比特,故其传输带宽为102400Mbit/s,即12800MB/s。

图1.32 历代DDR SDRAM

1.2.4 只读存储器

计算机中还有一种重要的只读存储器(Read-Only Memory,ROM)。顾名思义,这种存储器主要用于存放只读信息,如非必要,不对它进行写入。当然,RAM也可以做到这一点,但ROM拥有一项更宝贵的品质——非易失性。

1.MROM

最早的ROM是掩模只读存储器(Mask ROM,MROM)。这里的掩模指芯片制作过程中光刻时用到的掩模版,它强调着MROM中的线路(相当于所存储的数据)在生产时就被固定了。MROM的存储单元由单个NMOS组成,与RAM不同的是,它并不靠NMOS的电平状态来表示信息,而是通过NMOS的有无表示1和0。如图1.33所示,读取时,WL和BL都置高电平,前者令NMOS导通,导致后者被下拉置低电平,这一状态经过一个非门,最终在Q端输出高电平,即表示1。如果没有这一NMOS,BL上的高电平将直接输入非门,Q端输出低电平,表示0。

图1.33 MROM表示1的存储单元

图1.34为一个5行8列的MROM存储阵列示例,其中所存储的是1.1.3节中的加法示例程序:

0001 1000
0010 1001
0101 1000
1001 1010
1100 0000

图1.34 5行8列MROM存储阵列示例

2.PROM

MROM好比集成电路时代的硬连线,它的软件和硬件同生同灭,出厂之后便无法更改,是名副其实的只读存储器。然而,同样是追求艺术,有人希望买到现成的画作,有人却希望买到笔和白纸,自己作画。1956年,美籍华裔科学家周文俊发明了这样一张白纸——可编程只读存储器(Programmable Read-Only Memory,PROM),如图1.35所示。

图1.35 德州仪器PROM芯片TBP18SA030N[7]

[7] 图片来自维基百科“Programmable Read-Only Memory”词条。

PROM是双极结型晶体管(Bipolar Junction Transistor,BJT,俗称三极管)时代的产物,其存储单元由一个三极管和一根熔丝组成。如图1.36所示的为BJT电路符号,NPN在基极为高电平时导通,PNP在基极为低电平时导通。

图1.36 BJT电路符号

以NPN为例,PROM存储单元,如图1.37所示,三极管的集电极持续输入高电平,发射极与熔丝相连。当WL置高电平,NPN导通,BL就获得其集电极上的高电平,表示1。这种熔丝通常由电阻率较高的镍铬合金制成,和家用的保险丝一样,遇到大电流就会烧断,使用专用设备就可以定向烧断PROM存储阵列中的指定熔丝,相应的存储单元就永久断开了,表示0。

图1.37 PROM存储单元

这是烧断导线的做法,还有一种PROM恰恰相反,改用绝缘材料,所有存储单元默认为0。在此基础上用高压击穿其中部分绝缘体,使之永久导通,即可表示1。

3.EPROM

显然,无论是哪种PROM,所谓的“可编程”都是一次性的。追求艺术的人在得到“纸笔”之后,还想要一块“橡皮”,英特尔在1971年实现了这个愿望,推出了可擦可编程只读存储器(Erasable Programmable Read-Only Memory,EPROM)。

EPROM的存储原理还要从1967年的贝尔实验室说起。

某一天,贝尔实验室里的工程师们正在为集成电路排除故障,无意中发现某些MOS管的栅极接触不良,栅极和导线之间形成了一种类似电容的结构,储存了部分电能,这一状态下的MOS管可以导通,但需要施加比正常MOS管更大的电压。

受到启发的工程师们突发奇想,在MOS管原本的栅极上继续盖上一层二氧化硅,再在这层二氧化硅上盖一层金属,作为新的栅极,形成一种新型MOS管,如图1.38所示。原本的栅极被夹在两层绝缘的氧化物之间,尽管它是导体,却无法与电路中的任何导电部件相连,孤零零地漂浮着,故名“浮栅”。而最上层的新栅极发挥着原栅极的控制作用,故名“控制栅”。这种顶着“三明治”的MOS管称为浮栅场效应晶体管(Floating-Gate MOSFET,FGMOS)。

图1.38 从NMOS到FGMOS

对于NMOS而言,当栅极和漏极施加高电平,源极和衬底施加低电平时,由于电子在P型衬底顶部的堆积,源极和漏极下方的两块N型半导体之间会形成一条导电沟道,以此导通NMOS。同样的机制也在FGMOS身上奏效,并且,当人们不断加大控制栅上的电压时,终会遇见一个阈值,对导电沟道中的电子形成足够的吸引力,让它们克服原本过不去的二氧化硅层,隧穿进浮栅,如图1.39所示。

图1.39 FGMOS浮栅充电过程

而当各极断电,浮栅中的电子却保留了下来。这些电子将在FGMOS工作时,中和控制栅上原本足以导通FGMOS的电压。结果是,浮栅中有没有电子(准确地说是足量电子),决定着FGMOS在正常工作时的通断。

利用FGMOS构建EPROM的存储单元,浮栅中的电子少于某个阈值表示1,多于则表示0。EPROM出厂时,所有FGMOS的浮栅中都没有电子,即均可导通,所有存储单元都为1。根据需要,向其中一部分FGMOS高压写0,即实现了数据写入。

EPROM的“可擦除”通过波长为253.7nm的紫外线近距离照射实现,在紫外线光子的轰击下,浮栅下的二氧化硅层发生电离,就如同原本闭合的百叶窗被打开了,浮栅中的电子得以回到衬底中。大约几分钟后,整个EPROM芯片就全面归1。因此,EPROM和其他种类的芯片有着一个标志性的区分,它的中心嵌着一扇“透明窗户”,如图1.40所示。由于253.7nm的紫外线无法穿透大部分塑料和玻璃,因此窗户的材料采用了石英。

图1.40 EPROM芯片[8]

[8] 图片来自维基百科“EPROM”词条。

其实但凡波长在400nm以下的光都会造成EPROM的数据丢失,阳光只需要几个星期就可以让它“恢复出厂设置”,即使是普通的日光灯也能在几年时间内做到这一点。因此,正常使用EPROM时必须把这块窗户盖得严丝合缝。加之这块窗户增加了制造成本,许多厂商仅为调试用的芯片安装窗户,出厂的EPROM直接封死,将其用作一次性的PROM。英特尔在研制8048芯片时就是这么做的,这款芯片当时被用在计算机键盘和游戏终端里。

在没有高温和光照,保存得当的情况下,EPROM中的数据至少可以保存10年,部分可长达35年。由于数据的读取不会影响浮栅中的电子存量,因此在寿命期内,可以无数次读取。但是电子隧穿和光照电离会对二氧化硅层造成不可逆的损坏,这种损坏在积累了数千次后就会致使FGMOS失效,因此EPROM的擦写次数十分有限。

4.EEPROM

光照擦除方式必须将芯片从板子上拆下来,并且只能全片清空,不能定向修改。就在EPROM问世不久,日本的产业技术综合研究所就推出了不需要光照擦除的电擦除可编程只读存储器(Electrically-Erasable Programmable Read-Only Memory,EEPROM),如图1.41所示。

图1.41 EEPROM 芯片[9]

[9] 图片来自维基百科“EEPROM”词条。

EEPROM擦除是写0的逆过程,通过在衬底上施加高电压将浮栅中的电子“吸”回衬底。有了电擦除技术,可以直接在板子上对EEPROM进行擦写,而且不需要额外设备。并且,它的擦除以字节为单位,可以对其中的数据进行小范围的精确修改。随着技术的进步,如今的EEPROM可承受高达百万次的擦写。现在人们所熟悉的闪存就是一种特殊的EEPROM。

嗯?这还是只读存储器吗?

5.BIOS

大家已经了解到,计算机的基本工作模式十分简单,就是不断地重复从内存取指令和执行指令的步骤,然而内存是一种易失性存储器,其中的信息一旦断电就会消失。可以想象,当人们摁下开机按钮,电流流经计算机的全身,CPU从“冬眠中苏醒”,摩拳擦掌,准备大展身手,却猛地发现内存中空空如也……

在早期的计算机中,所有的运行步骤都是通过硬连线实现的,当电源被接通,电流将依次激活一条条电路。后来穿孔技术盛行,计算机总能够从第一张穿孔卡片或穿孔带的头部得到第一条指令。到了电子计算时代,承载第一批指令的任务就交给了ROM。

ROM中的程序是极少变动的,早期ROM在硬件层面的布线则直接代表了程序本身,这些程序的主要作用也是和计算机中最底层的硬件打交道,因此,虽然是软件,但人们更习惯用固件(Firmware)来称呼它们。除了计算机,固件也常见于各种嵌入式设备,包括遥控器、打印机、电子秤、电视机、电饭锅等。计算机的主板上散布着各司其职的固件,其中最关键的是基本输入/输出系统(Basic Input/Output System,BIOS)。

当人们按下开机按钮后,往往需要等待一段时间才能见到操作系统的启动界面,这期间的屏幕往往一片漆黑,显示一些简单的文字信息,一闪而过,看起来好像什么都没发生,其实背后,BIOS正在“辛勤劳作”。

给计算机“上电”后,BIOS第一时间“进驻”内存[10],驱动CPU。它的首要任务是“上电”自检(Power-On Self-Test,POST),对CPU、内存、显卡、网卡、硬盘等硬件进行基础扫描,确保计算机硬件无缺失、无故障,并对一些硬件进行初始化,为操作系统备好运行环境。当然,硬件的种类千差万别,BIOS“认”不全,一些功能强大的硬件(如独立显卡和独立网卡)便配有自己的BIOS,辅助完成这一过程。

[10] 早期的BIOS直接在ROM上运行,在2007年以前,ROM和RAM的速度总是“你追我赶,难分伯仲”,但2007年后,RAM巩固了绝对领先的地位,BIOS便顺理成章地运行在内存上了。

接下来,BIOS按设定好的顺序轮询几个可能拥有操作系统的设备,最常见的是硬盘驱动器,其次是光驱、USB存储器、网卡等,查看它们头部是否有完整的引导程序,一旦找到就出让控制权(剩下的设备就不查看了),由引导程序启动操作系统。

早期的操作系统(如DOS)在运行时还需借助BIOS实现对硬件的输入/输出,现在的操作系统则完全可以“自理”,计算机完成启动后,BIOS基本“休眠”。

BIOS还提供了重要的硬件配置功能,如调整启动设备的顺序、修改系统时间、设置开机密码(不是操作系统的登录密码)等[11]。在操作系统启动之前,根据黑幕界面上的提示按下相应按键(如F1、F10、Esc等),就可以进入BIOS的设置界面。图1.42给出了传统的BIOS设置界面,它十分简陋,只提供一片蓝色背景的纯文字信息,直到后来出现了新的BIOS标准——统一可扩展接口(Unified Extensible Firmware Interface,UEFI),BIOS设置界面才丰富多彩起来,并支持鼠标操作,如图1.43所示。如今,UEFI BIOS已经全面取代了传统BIOS,但许多计算机(尤其是笔记本电脑)仍然保留着这一“朴素”的设置界面。

[11] 早期的BIOS不提供设置功能,一些必要的配置通过主板上的硬开关实现。

图1.42 传统的BIOS设置界面[12]

[12] 图片来自维基百科“BIOS”词条。

图1.43 UEFI BIOS设置界面

和BIOS本身不同,这些设置信息的变动更为频繁(尤其每时每刻都在更新的系统时间),因此不适合存储在ROM中,SRAM成为更好的选择。由于SRAM的CMOS工艺,存储这些信息的芯片常被称为CMOS芯片(CMOS RAM)[13],这真是个糟糕的称呼。更糟的是,许多地方还会把BIOS和CMOS混用,使人十分困扰。RAM是易失性的,因此主板上通常配备一枚纽扣电池——CMOS电池,如图1.44所示,以维持CMOS中的信息。

[13] 现在的CMOS RAM集成于南桥芯片,不再是独立的一块芯片。

图1.44 计算机主板上常见的CR2032纽扣电池[14]

[14] 图片来自维基百科“Nonvolatile BIOS Memory”词条。

1995年,EEPROM的性价比开始赶超EPROM,BIOS开始普遍集成在EEPROM或闪存中。因此,在必要时(如更换了新型硬件),用户可以自行升级BIOS。

不过,即使没有了CMOS RAM,主板却依然离不开CMOS电池,因为时钟的运转需要电量来维持。毕竟,人们总不希望每次开机后看到的系统时间都是几十年前的某个凌晨吧?

1.3 外存:机器的“卧室”

每当计算机结束了每秒数十亿次的高强度“劳作”,就把自己的“思想”和“知识”安顿到一个狭小的盒子——硬盘中。这里是机器的“卧室”,它的完好,保证计算机的“灵魂”不灭。

说起硬盘,人们常会提到另一个称呼——外存,也就是与内存相对的外部存储器。其实硬盘只是外存的一种,软盘、用于服务器数据备份的磁带、早已退出主流应用的光盘、经常用来传递资料的U盘等都属于外存。这些不与CPU直接交互的存储器也称为辅助存储器或二级存储器。

1.3.1 机械硬盘——电子计算时代的机电遗风

原本“硬盘”一词只有一个所指,结果技术的革新带来了混淆视听的固态硬盘,为做区分,传统硬盘被套了个前缀,称为“机械硬盘”,而“硬盘”则成了机械硬盘和固态硬盘的统称。其实固态硬盘根本不是“硬”盘,其英文为Solid-State Drive/Disk,直译过来就是“固态驱动器”或“固态盘”,哪有“硬”(Hard)字可言呢?不过这一称呼早已约定俗成,也挺容易被人接受。本小节中如非特殊指明,“硬盘”便指机械硬盘,如图1.45所示。

图1.45 硬盘[15]

[15] 图片来自维基百科“Hard Disk Drive”词条。

硬盘其实是对硬盘驱动器(Hard Disk Drive,HDD)的简称,光有“盘”可不够,还需要一个能驱动它运作的驱动器。严格地讲,硬盘只是硬盘驱动器中的盘片,但通常不做这一区分,本书亦然。

硬盘的名称是相对于软盘(Floppy Disk)来说的,如图1.46所示,两者的原理类似,但盘片材质的软硬不同。见过软盘的读者肯定知道,掰开塑料外壳,里面的盘片像塑料纸一样柔软。

图1.46 各种尺寸的软盘[16]

[16] 从左至右尺寸依次为8英寸、5.5英寸和3.5英寸。图片来自维基百科“Floppy Disk”词条。

1.内部结构及工作形态

抛开精密的控制电路,硬盘内部并不复杂,如图1.47所示,最关键的两个部件是存放数据的盘片(Platter)和读写数据的读写头(Read/Write Head,也称磁头)。单块硬盘中往往叠加着多个盘片,每个盘片的正反面都配有单独的读写头,如图1.48所示。读写头位于执行臂(Actuator Arm)的末端,执行臂在执行器(Actuator)的驱动下来回摆动,配合盘片的旋转,读写头可以近距离“接触”(并不真的碰到)到盘片的每一寸“肌肤”。相比计算机中其他令人费解的半导体芯片,这是一种肉眼就能看懂的机电结构。

图1.47 硬盘主要部件特写[17]

[17] 原图来自维基百科“Disk Read-And-Write Head”词条。

图1.48 三层盘片配备的读写头[18]

[18] 图片来自维基百科“Hard Disk Drive”词条。

硬盘的工作形态和留声机有点类似,“唱头”在“唱片”上飞快地读写着数据。

盘片的转速通常为4200r/min~15000r/min[19],目前个人计算机中硬盘的主流转速是5400r/min和7200r/min。执行臂也不示弱,其摆动的加速度可达到550个g(重力加速度)。

[19] 转/分(revolutions per minute)。

2.存储原理

盘片光滑如镜,看似简单却内有乾坤。它通常由铝(合金)、玻璃或陶瓷制成,表面被刷了很多层材料,像一个怕冷的人身上套着一件又一件衣服:贴身的是一件由多种合金混合而成的非磁性“打底衫”,接着是一件背负着数据存储使命的磁性(氧化铁、钴合金等)“毛衣”(这件毛衣只有10~20nm的厚度),再套上起保护作用的碳质“卫衣”,最后再披上一件名为聚四氟乙烯(PTFE)的纳米“外套”。

众所周知,磁性物质都具有南北两个磁极,恰好可以用来表示二进制中的0和1,这也是所有磁存储器的基本原理。盘片靠磁性涂层具备了数据存储的能力,因此盘片也被称为磁盘(Magnetic Disk),软盘过时之后,磁盘也成了硬盘的代名词。

别看该盘片小巧,在微观尺度上却是一片“广袤天地”。其正反两面均可存储数据,也都配有相应的读写头。从中心转轴到外边缘,盘片的表面在逻辑上划分出了许多个同心圆,这些同心圆称为磁道(Track),每个磁道又划分成一段段小圆弧,称为扇区(Sector),如图1.49所示。

图1.49 磁道与扇区示意图[20]

[20] 图片来自维基百科“Zone Bit Recording”词条。

越是外圈的磁道有着越多的扇区,同样旋转一圈,读写头掠过的范围也就越大。最外圈的磁道也就是人们常说的0磁道。

每个扇区继续划分出一定数量(通常为512个或4096个)的比微米还小的磁区(Magnetic Region),每个磁区中随机分布着数百颗最基本的磁粒(Magnetic Grain),每颗磁粒有着自己的南北极,当它们朝向一致时,这一磁区作为一个整体就具有了表示0或1的特质,如图1.50所示。

在盘片微米级的尺度上和每秒数千乃至上万圈的转速下,绕着线圈的读写头将电磁学发挥到了极致。当线圈通电时,读写头产生的磁场将下方的磁区迅速磁化,电流方向不同,磁化的方向也就不同;当线圈不通电时,读写头在掠过磁区时切割磁感线,当两个相邻的磁区朝向相反时,电磁感应从而产生电压脉冲(Voltage Spike)被识别为1,反之无脉冲,为0,如图1.51所示。

图1.50 磁盘中的磁粒[21]

[21] 原图来自《计算机文化(原书第15版)》P53。

图1.51 磁区读数原理

为了提高盘片的存储容量(也就是单位面积内的磁区数量),工程师不断缩小磁区和读写头尺寸,磁区的排布也从横向变成了纵向。2005~2006年,水平存储被垂直存储取代,如图1.52所示。相比水平存储,垂直存储有着更高的存储密度。

图1.52 横向磁区和垂直磁区[22]

[22] 图片来自维基百科“Hard Disk Drive”词条。

3.“车祸现场”

由于读写头和盘片的距离越来越近,近到了只有几纳米,由盘片飞速旋转产生的气压升力将读写头稳稳地托起——这真是一项令人心惊胆战的极限运动。

因此,大家也许听到过一些专业人士的忠告:个人计算机或笔记本电脑在开机时最好不要随便用力移动。因为外界的震动可能导致读写头猛地“栽到”盘片上,后果有多严重?不妨想象一下盘片的转速有多快。打个比方,如果7200r/m的盘片上停着一辆微型汽车,它便相当于在以超过120公里的时速飞驰,一旦发生车祸,后果不堪设想!读写头会陡然化身“耕犁”,将下面的磁道“连根刨起”,材料碎粒四处飞溅,散落到盘片表面,如图1.53所示。

图1.53 划伤的磁道与散落的碎粒[23]

[23] 图片来自维基百科“Head Crash”词条。

多么惨烈的“车祸现场”,这对用户来说是无法估量的数据丢失,而这一切发生在瞬间。

好在最外面的聚四氟乙烯层和碳层能将盘片从大部分的意外磕碰中保护下来,硬盘盒外侧的橡胶垫也具有一定的缓冲作用,现在有一些硬盘还加装了一种称作加速计(Accelerometer)的传感器,可以监测突发性震动,在必要时将读写头迅速“停泊”。

4.发展历程及主要参数

1956年9月14日,IBM推出了世界上第一块硬盘IBM 350,它是IBM最后一台电子管计算机IBM 305 RAMAC的外存部件,如图1.54所示。这台计算机重达1吨,需要放在长15m、宽9m的大房间里,每月租金高达3200美元,相当于现在的28546美元。

图1.54 IBM 305 RAMAC[24]

[24] 靠近镜头的正是两个350硬盘机柜。图片来自维基百科“IBM 305 RAMAC”词条。

IBM 350硬盘也是个大家伙,长约152cm、宽约74cm、高约172cm,足有两个中型冰箱那么大。74cm的高度中堆叠着50块24英寸的盘片(图1.55),24英寸是什么概念,已经接近10个现在的2.5英寸笔记本电脑硬盘的大小。可它的容量却只有3.75MB,不过这在当时已经绰绰有余了,因为它能代替64000张穿孔卡片。有趣的是,以当时的技术容量完全可以做到5MB以上,IBM的市场部门却坚决反对,因为他们不知道该如何向客户推销如此大容量的机器。

图1.55 一张350盘片[25]

[25] 图片来自维基百科“IBM 305 RAMAC”词条。

IBM的工程师只为这50个盘片安装了一对磁头,读写数据时先要上下移动选择盘片,然后伸进去寻道。在盘片1200r/m的转速下,数据访问的平均延迟时间为600ms,读写速度是每秒8800个字,对比当时主流的穿孔卡片可算是飞速。到了60年代初,IBM陆续推出的硬盘为每个盘片都安装了一对磁头,这一结构沿用至今。

从发明到现在短短几十年,硬盘的各项参数沿着指数曲线飞跃发展,堪称人类现代技术爆炸的典型。它的尺寸从一台冰箱大小减小到可以揣进裤兜的3.5英寸(台式机硬盘)和2.5英寸(笔记本电脑硬盘和移动硬盘),容量从仅能保存一首MP3歌曲暴增至TB级,价格从贵得离谱跌到几毛钱1GB,重量从几百公斤减至几百乃至几十克,数据访问时间从600ms缩短至10ms以内,使用寿命(平均故障间隔时间)从2000小时延长至近300年。倒是转速发展得最慢,从最初的1200r/m到如今消费级主流的5400r/m、7200r/m,甚至连量级变化都没有,即便是企业级硬盘也只有10000r/m、15000r/m,这正是机械结构的局限所在。

图1.56给出了各种尺寸的硬盘,浓缩着硬盘的发展历程。从上至下、从左至右尺寸依次为8英寸、5.25英寸、3.5英寸、2.5英寸、1.8英寸和1英寸。2009年起,所有厂商停产了2.5英寸以下的小硬盘,固态硬盘性价比的提升使得继续缩小机械硬盘的尺寸已经没有意义。

图1.56 各种尺寸的硬盘[26]

[26] 图片来自维基百科“Hard Disk Drive”词条。

市场上曾出现过200多家硬盘厂商,一轮轮的商业并购下来,成就了如今希捷、西数和东芝三足鼎立的局面(图1.57)。

图1.57 各大硬盘厂商的成立及并购年份[27]

[27] 图片来自维基百科“Hard Disk Drive”词条。

作为普通消费者,大家最关心的就是硬盘的容量和读写速度。到2010年为止,硬盘容量的增速还基本遵循着摩尔定律(每两年翻一番),如图1.58所示。2010年之后硬盘价格的跌速和容量的涨速都出现疲软,这预示着硬盘存储技术的发展已经开始接近“天花板”。

图1.58 1956~2009年硬盘容量的增长趋势[28]

[28] 图片来自维基百科“Hard Disk Drive”词条。

注:CAGR复合年均增长率。

至于读写速度,受限于执行臂摆动的速度、盘片的转速和盘片的存储密度,这样的机电结构已经很难有质的突破。相比纯电子结构的CPU和内存,硬盘仿佛是个妄图追上汽车的人,跑得十分“狼狈”。

这就引出了下面将要介绍的“闪存”的概念。

1.3.2 闪存

1.原理简介

人们常说的闪存,是闪速存储器(Flash Memory)的简称。它是一种特殊的EEPROM,出现于20世纪80年代,最早由日本东芝公司的一名工程师发明。其擦除速度之快,令他的同事联想到相机的闪光灯(Flash),因而得名。

原本EEPROM中,电子在浮栅和衬底之间的来回隧穿是个很慢的过程。舛冈富士雄安排一定数量的FGMOS共用衬底,这样就可以同时把它们浮栅中的电子一齐吸出来,实现批量快速擦除。这些共用衬底的FGMOS被归为一个块(Block),闪存的存储阵列由大量这样的块组成,每块的大小为16KB~512KB。

如果沿用ROM的存储阵列,闪存中的FGMOS如图1.59所示排布(通过在NMOS的电路符号中添加一横表示FGMOS)。每个FGMOS的控制栅都与字线相连,源漏其一与位线相连、其二置低电平。当人们把目光放在其中的某根位线上时会发现,但凡有某条字线置高电平导致其上的FGMOS导通,该位线就会被拉至低电平,识别为1。这一规律形似或非逻辑,因此这种闪存被称为或非闪存(NOR Flash)。

图1.59 或非闪存存储阵列及其中单列

或非闪存以字节或字为单位读写数据,却以更大的块为单位进行擦除,完美契合了固件指令读取和高速升级的需求,成为传统EEPROM的绝佳替代品。

但舛冈富士雄没有止步于此,为了减少布线提高存储密度,他将原本并联在位线上的FGMOS用串联的方式源漏相接形成字线,如图1.60所示。观察其中某根位线,只有当所有字线都置高电平导致各FGMOS导通,该位线才会被拉至低电平,识别为1。这一规律形似与非逻辑,因此这种闪存被称为与非型闪存。本节下文所提闪存如无特殊说明皆指与非闪存。

图1.60 与非闪存存储阵列及其中单列

为了获得更快的读写速度,舛冈富士雄还拉长了字线,每根字线上挂接着上万乃至十余万个FGMOS,远远超出了一个字的长度。这样的一串FGMOS称为页(Page)。因此,与非闪存在划分为若干块的基础上,每块进一步划分为若干页。常见的页的大小为4KB、8KB、16KB,每块包含64或128个页。

与非闪存以页为单位进行读写,针对连续存储的数据比或非闪存更有优势。且前者存储单元的尺寸仅有后者的五分之二,拥有更高的存储密度,大大降低了建造大容量芯片的成本,是充当外存的上好材料。

1987年,东芝将与非闪存投入量产,此后,英特尔、三星、闪迪等半导体巨头加入市场,芯片容量遵循着摩尔定律爆发式地增长,如图1.61所示。

图1.61 1989~2019年与非闪存芯片容量走势

为了挖掘闪存的容量潜能,这些公司甚至“细数”起浮栅中的电子数量,让单个FGMOS存储更多比特。假设浮栅中最多可充入N个电子,原本的做法是将N/2以下的电子数判定为1,N/2以上判定为0,以此表示1比特。后来,这个N被划分为4段,0~N/4判定为11、N/4~N/2判定为10、N/2~3N/4判定为01、3N/4~N判定为00,以此表示2比特。再后来,N继续被划分为8段乃至16段,以分别表示3和4比特[29]

[29] 表示1比特的存储单元称为单层单元(Single-Level Cell),简称SLC,其1条字线表示1个页;表示2比特的存储单元称为多层单元(Multi-Level Cell),简称MLC,其1条字线表示2个页;表示3比特的存储单元称为三层单元(Triple-Level Cell),简称TLC,其1条字线表示3个页;表示4比特的存储单元称为四层单元(Quad-Level Cell),简称QLC,其1条字线表示4个页。虽然后三者比SLC有着更高的存储密度,但需要更长的读写时间,以精确控制电子数量的进出,性能和寿命都不如SLC。

如今,以U盘、内存卡、固态硬盘和手机存储为代表的与非闪存已经成为计算机外存的主角。在2009年,固态存储厂商PureSilicon成功将1TB的闪存芯片集成到2.5寸的硬盘中,宣告着机械硬盘在容量上的优势开始丧失。

2.固态硬盘发展历程

固态硬盘(Solid State Disk),简称SSD,最早出现于1976年,那时闪存尚未问世,固态硬盘中封装的是易失性的DRAM,总容量2MB,配有持续供电的电池,如图1.62所示。DRAM性能强劲,但成本太高,2004年,闪存的成本降到了DRAM之下,SSD中的存储芯片被逐步替换为闪存。到2009年,DRAM SSD已经退出主流市场,本节下文所提SSD如无特殊说明皆指与非闪存SSD。

最早的闪存SSD产品是1991年闪迪公司推出的一款PC卡[30],如图1.63所示,容量为20MB,被IBM公司用于ThinkPad系列笔记本电脑中。

[30] PC卡也称PCMIAC卡,是个人计算机存储卡国际协会(Personal Computer Memory Card International Association,PCMIAC)于1990年制定的一种卡型,活跃于早期的笔记本电脑中。

图1.62 Dataram公司于1976年推出的DRAM SSD产品[31]

[31] 图片来自Dataram公司的1977 Annual Report

图1.63 闪迪公司于1991年推出的闪存SSD产品

2006年,索尼公司推出了第一台出厂搭载SSD的个人计算机VAIO UX90,吹响了SSD向消费级市场进军的号角。2007~2008年,戴尔、华硕、苹果、联想等主流计算机厂商纷纷推出搭载SSD的笔记本电脑产品。2008年,SSD的制造商已经超过百家。2010年,苹果公司将SSD定为MacBook Air的标配硬盘。这一年,全球的SSD市场总额达到了10亿美元。接着,SSD越来越普及、也越来越受欢迎。图1.64为3种主流接口的SSD。

图1.64 SATA、mSATA和M.2接口的SSD

SSD的繁荣也不是一蹴而就的,它的可靠性被用户质疑了多年。由于闪存在物理上有着读写磨损、电荷泄漏等“骇人听闻”的先天缺陷,SSD无法有效保存数据的言论在媒体中曾经接连不断。好在SSD的设计者引入了许多优秀的策略,以应对这些缺陷。事实证明,SSD的可靠性经受住了时间的检验,使用寿命往往远超厂商在规格中标注的限值,这才消除了人们的顾虑。

机械硬盘在读写头完成寻道后可实现约200MB/s的连续数据访问,而这却只是普通SSD的速度,优质SSD的连续访问可达3500MB/s,企业级SSD甚至支持以GB级的每秒吞吐量。SSD除了没有机械部件,还具有抗震、底噪、低功耗等优势。

3.得力管家FTL

以SSD为代表的闪存设备主要部件除了闪存,还有控制器和作为缓存的RAM。RAM适配着外存与内存之间的速差,是数据进出的必经之地,如图1.65所示。此外,RAM还是控制器对闪存进行管理的核心场所,控制器在这里构筑起一个功能强大的闪存转换层(Flash Translation Layer,FTL),它是闪存的资源“管家”,处理着许多操作系统不得而知的问题,如图1.66所示。

图1.65 缓存的数据桥梁作用示意图

图1.66 FTL的作用示意图

FTL的首要任务是地址映射,即将操作系统所见连续的存储空间映射到物理的闪存空间,为系统提供一本索引数据的目录。如图1.67所示,对于操作系统来说,闪存就像一排按序编号的数据“抽屉”,可它不知,这些“抽屉”在闪存中其实是乱序的。地址映射可以以块或页为单位,前者表达映射关系的映射表更小,但读写时以块为单位进行缓存,效率较低,一般应用于U盘,所以人们在用U盘复制大量小文件时速度会很慢。SSD一般使用页映射,读写更灵活,但映射表比块映射大得多。

图1.67 FTL地址映射示意图

不过,为什么FTL要维护这么一张混乱的映射表呢?直接顺序对应不好吗?其实这与闪存的固有缺陷和节省布线的副作用有关。

FTL和用于固件的与非闪存不同,与非闪存是允许带着少量的天然坏块出厂的,这些块中包含不能正常使用的存储单元,按理说整个芯片都应当作为次品处理,但块与块之间其实互不干扰。FTL可以通过坏块管理建立一个黑名单,将它们排出映射表。这么做大大“提高”了良品率,进而降低了平均成本。同时,闪存在经历过一定的擦写次数后,氧化层的老化也会使FGMOS失效,进而产生新的坏块,FTL会及时将它们加入黑名单,为整个芯片的继续使用保驾护航。

理论上,SLC存储单元可以承受高达10万次的擦写,达到这一量级就容易贡献坏块。而根据二八定律,闪存上大部分数据是长时间“躺着不动”的,别说擦写了,可能连读取都很少,而小部分数据的使用和更新频率却出奇的高,如果放任不管,这部分块会在整个闪存芯片还远没有接近寿命极限时就报废。为了规避这种“贫富差距”,FTL需要进行磨损均衡,它跟踪每个块的擦除次数,当有新数据需要写入时,尽量挑选擦除次数少的块。此外,FTL还会趁空闲时偷偷将那些常年没有变动的块上的数据搬到擦除次数高的块上。

FTL尤其热衷于在“私底”下完成数据的“来回腾挪”,这是其他存储介质没有的特性。由于闪存以块为单位进行擦除,当人们删除某些页上的文件,其实FTL仅仅是将这些页也标记为“已删除”,数据仍在,只有当块上的所有页都被标记为“已删除”,才能进行全块归1,真正擦除数据。同时,闪存在写入数据时,只能将1改为0,0改为1必须靠擦除。这意味着,被标记为“已删除”而尚未擦除的页由于不是全1,无法重新写入数据,成为了既占用空间又一无是处的垃圾。久而久之,当所有块中的页要么存有数据、要么被标记为了“已删除”时,新到的数据将无从写入,这时FTL就不得不进行垃圾回收——挑选一个块,暂时读出其中存有数据的页,然后全块擦除,再把新旧数据一起写入。图1.68以简化的形式演示了这一过程,假设1个块由9个页组成,一条数据占用1个页。

图1.68 垃圾回收示意图

1)起初,人们拥有完全空白的块。

2)渐渐地,块中塞满了数据——A、B、C、D、E、F、G、H、I,无法再写入更多数据。

3)使用过程中,人们删除了A、B、D、F、H、I,块中只剩下C、E、G,但所有页都仍是不可写的。

4)当闪存中的所有块都处于这种状态,而此时来了一条新数据J,无处可写,FTL就将C、E、G读入缓存,擦除块,最终将C、E、G、J写入。

闪存用久之后,这种情况将频繁出现,写入数据时需要FTL进行额外的擦除和读写,拖累了数据写入的效率,这一现象称为写放大。这也是人们的手机总是越用越“卡”的重要原因。所以手机的机身存储越大越好,即使人们用不了那么多。

按理说,闪存的读取不涉及电子隧穿,相比写入和擦除,是最不容易制造麻烦的操作。然而,当读取某一页,即存储阵列中的某一行时,不光需要给该行的字线加高电平,还需要给所有其他字线都加高电平。浮栅中的电子会提高FGMOS导通所需的控制栅电压,即存储0的单元导通所需的字线电压要高于存储1的单元,记前者为V0、后者为V1,即V0>V1。如图1.69所示,以读取第二行为例,该行字线加置V1,导通该字线上为1的FGMOS,其余字线置V0,导通这些字线上所有为0的FGMOS,为所有位线的正常工作提供条件。可见,读取一页时,块中其他页上的FGMOS会被施加更高的控制栅电压,虽然这个电压不大,可多少会对电子产生吸引,久而久之就增加了浮栅中的电子,导致了莫名其妙的写0。这种现象被称为读干扰。为了避免读干扰产生的数据错误,FTL跟踪每个块的读取次数,当这个次数达到某个阈值,就必须将数据重写一遍(读出来、擦除块、写回)。优秀的FTL会根据闪存的“年龄”动态调整这个阈值,“年龄”越大,阈值越小。

图1.69 与非闪存页读取示意图

正如充满气的气球无论扎得多么紧最终都会漏气一样,时间久了,浮栅中的电子也会缓缓逃逸。在久置不用的情况下,老旧闪存中的数据可能只能自持1~2年。因此,FTL在空闲时会不时做一次全盘扫描,以及时发现电子泄漏产生的比特翻转,在出错率超出软件层面的纠错能力之前进行重写。但只要不上电,FTL也无能为力。所以,闪存不适合作为归档存储介质,这也是SSD尚无法完全替代机械硬盘的一大原因。

1.4 时钟:数据“交响乐”的指挥家

计算机的运行像一曲气势恢宏的“交响乐”,无数由0和1组成的“音符”在主板上高频而有序地“跳动”着,“奏出”和谐的数据乐章。不同的芯片扮演不同的“乐组”,彼此独立却又紧密地合作。芯片中大大小小的功能电路负责着各自的“乐器”,任谁的一次“抢拍”都会破坏整场演出。它们需要一名出色的“指挥家”。

1.4.1 时钟信号

在计算机纷乱的0、1信号中,有一个脉冲信号十分特殊,它在0和1之间做着周期性的来回切换,这和其他看起来毫无规律、需要人为赋予含义的信号不同,反倒像“日夜轮回”这样亘古不变的自然现象。它就是时钟信号(Clock Signal),约束着整机工作节奏的“神秘力量”,如图1.70所示。

图1.70 时钟信号

在庞杂的集成电路中,一条数据从某个部件出发,进入另一个部件进行某种处理,与此同时,也许另一条数据也会来到此地,一同被处理。处理数据的部件往往需要接收多个输入数据,而由于导线、元器件时延等原因,这些数据在高频跳变的状态下几乎不可能按某种约定同时抵达输入端。如图1.71所示,当预期在某个时刻向AB两端同时输入1时,由于B端的1稍稍迟到了一会,便造就了一个“A端输入1,B端输入0”的瞬间,Q端也会在这一瞬间产生不合预期的输出。虽然,正确的输出将紧跟而上,但Q端后面的接收者又将如何在两者之间取舍呢?是否也将这个错误的瞬间传递下去?

好在,有一种专门用来控制输入有效性的信号——使能信号(Enable Signal)。以高电平有效为例,只有当使能信号为高电平时,部件才能收到数据,否则它将忽略一切输入。这一逻辑可以靠一个简单的与门实现,如图1.72所示。使能信号扮演着开关的角色,只有当开关打开,跳动的输入信号才能被功能电路收到,如图1.73所示。

图1.71 输入不同步示意图

图1.72 一种简单的使能信号接入方案

图1.73 使能信号作用示意图

当部件的多个输入端都以这种方式接入同一个使能信号,就能在使能信号的控制下达成同步,如图1.74所示。时钟信号就是这样一种特殊的使能信号,它的布线像毛细血管一样深入计算机中每一个需要时序控制的部件,时钟则好比心跳,每隔一个时钟周期就对这些部件进行一次供血(使能)。

计算机就是这样一台状态离散的机器,每过一个时钟周期,就从上个状态跳转到下个状态,这是一幕幕精准的“台前表演”。而状态与状态之间,则是导线传递信号,元器件切换0、1的繁忙“幕后排练”。

图1.74 使能信号同步示意图

1.4.2 晶振

CPU、内存、显卡、声卡等零部件正是在统一的时钟信号的驱动下,才能有条不紊地协同工作。这个重要的信号来自主板上的时钟发生器(Clock Generator),它由晶体振荡器和一部分辅助电路组成,如图1.75所示。

图1.75 基于14.3MHz晶振和ICS 952018AF芯片的时钟发生器[32]

[32] 图片来自维基百科“Clock Generator”词条。

晶体振荡器(Crystal Oscillator)简称晶振,顾名思义,是一种通过晶体的来回振荡产生时钟信号的元器件。和摆钟中用于计时的钟摆一样,晶体振荡也具有稳定的周期性,其原理要追溯到1880年由居里夫人的丈夫皮埃尔•居里(Pierre Curie)和他哥哥雅克•居里(Jacques Curie)发现的压电效应(Piezoelectric Effect)。他们分别对电气石(碧玺)、石英、托帕石(黄玉)、蔗糖、酒石酸钠钾(罗谢尔盐)等晶体(图1.76)施加压力,发现它们都可以在电路中制造微弱的电流,把机械能转换成电能。其中,石英和酒石酸钠钾的压电效应尤为明显。

图1.76 居里兄弟演示压电效应的晶体[33]

[33] 图片分别来自维基百科“Tourmaline”“Quartz”“Topaz”“Sugarcane”“Potassium Sodium Tartrate”词条。

压电效应的本质,是晶体受外力挤压后产生极其微小的形变,内部原本均匀排布的电荷随之失衡。以由二氧化硅(SiO2)组成的石英晶体为例,其内部结构如图1.77(a)所示,灰球表示硅原子,红球表示氧原子,每个硅原子与4个氧原子相连,每个氧原子与2个硅原子相连。当以某个角度去观察这一结构,会看到一种由3个硅原子和3个氧原子构成的六边形切面,如图1.77(b)所示。

图1.77 石英晶体结构(局部)

未受压的情况下,带正电的硅原子和带负电的氧原子分布规整,晶体各向呈电中性,如图1.78(a)所示。当人们给这个六边形的上下施压,如图1.78(b)所示,六边形被挤扁,相对来说,下方的两个氧原子上移了一些,上方的两个硅原子下移了一些,导致整体负电荷的“重心”上移,正电荷的“重心”下移。如此一来,晶体就成了上表面带负电荷、下表面带正电的状态。反之,晶体受到拉伸会有相反的带电状态。

图1.78 石英晶体受压示意图

1881年,也就是压电效应被发现的第二年,法国物理学家加布里埃尔•李普曼通过基本的热力学原理推导出逆压电效应,即具有压电效应的晶体在外加电场的作用下,会产生机械形变。居里兄弟很快验证了这一推论。这意味着,借助这类晶体,就能实现机械能和电能之间的相互转换。

由于声音的本质是物质的振动,压电和逆压电效应被广泛应用于声呐、留声机、声控开关、话筒、扬声器等声电设备。当然,最重要的应用还是电子设备中的晶振。1917年,贝尔实验室使用酒石酸钠钾做出了世界上第一块晶振。1921年,世界上第一块石英晶振于美国维思大学问世。1928年,贝尔实验室开发出了世界上第一台石英钟,其30年内只有1秒的误差。

石英晶体在外加电场的作用下由于逆压电效应发生形变,如果这个外加电场是交变的,那么石英的形变就会在两个相反的方向周期性地交替进行,形成振动,如图1.79所示。本来,振动的幅度是极其轻微的,但当交变电场的频率与石英的固有频率相吻合时,共振便产生了,石英以最大的幅度振荡起来,通过压电效应开始对外输出时钟信号。这个外加的交变电场通过复杂的电路实现,通常由电容、三极管、电阻等元器件组成,电容重复着充电和放电的过程,像打乒乓一样和石英来回交换电能,三极管作为放大器对实时损耗的电能进行补充。

图1.79 晶体振荡的几种模式[34]

[34] 图片来自维基百科“Crystal Oscillator”词条。

通常,晶振中的石英被切割成矩形或圆形薄片,或者音叉状(这种晶振多用于石英钟表),如图1.80所示,而后被封装进如图1.81所示的各种形状的外壳中。如果读者感兴趣,可以在废弃的主板上找到并拆开它,一窥究竟。

图1.80 晶振中的石英晶体[35]

[35] 图片来自维基百科“Crystal Oscillator”词条。

图1.81 几种常见的晶体封装[36]

[36] 图片来自维基百科“Crystal Oscillator”词条。

石英晶振具有很高的稳定性,在原子钟出现之前,是世界上最精确的计时装置。石英钟表中以32768Hz振荡的小“音叉”即使在与常温相差20℃的环境中每年也仅产生约8分钟的偏差,而在与常温相差10℃的环境中年偏差更小——约2分钟。当然,在精度要求不高的应用场景中,人们也会选择成本更低的压电材料,如陶瓷。

1.4.3 倍频

石英的固有频率取决于晶体的尺寸、形状和切割方向等因素,常规的石英晶振标称在几十千赫兹到几百兆赫兹之间,事实上,30MHz以上的晶振需要非常薄的晶体切片,很难制造。那么动辄以GHz为单位的CPU主频是怎么来的呢?这就涉及倍频的概念。

原来,晶振的主要价值在于稳定,而非高频,真正的高频振荡还得靠纯电子电路产生。如图1.82所示,倍频电路主要由鉴相器、低通滤波器、压控振荡器和分频器等部件组成,由于篇幅有限,这里只简单介绍其整体工作原理,不再逐一探讨各个部件。鉴相器接收两个不同频率的信号输入,一个是来自晶振的基准频率fr信号,另一个是来自分频器的反馈信号,将两者的相位差转换为与之成正比的电压值UdUd经过低通滤波器滤除高频分量后形成对压控振荡器的控制电压Uc,压控振荡器在Uc的作用下调整振荡频率fo,分频器将这一频率的N分之一反馈给鉴相器,信号在环路中不断循环,调整着fo,直到fo/N=fr达到稳态,最终实现对frN倍频。

在计算机中,时钟信号从晶振出发,经过倍频电路步入总线,形成频率多为100MHz的总线时钟。对CPU来说,这个100MHz频率是外频,是和其他芯片进行通信的频率,而其内部,需要继续将其频率增加几十倍,最终获得人们所熟悉的以GHz计的主频。

图1.82 倍频原理

有些CPU允许用户在BIOS中手动设置这一倍频值,给超频提供了可能,通常这是极客玩家的选择。超频后的CPU产生更高的能耗,处于超负荷的工作状态,主板、电源和风扇也经受着超常的考验,将大大降低整机的稳定性。所幸的是,现在的CPU引进了睿频技术,能根据当前的计算任务自动调整工作频率,收到低功耗、高效能的效果。

除了CPU,其他芯片也会按需自行倍频,典型代表是内存。1.2.3节在罗列历代内存时,提到了许多令人困惑的工作频率,如133⅓MHz和166⅔MHz。“罪魁祸首”其实是早期流行的33⅓MHz总线时钟,这些古怪的频率都是在此基础上倍频的结果,例如:

33⅓MHz的4倍频“衍生”为133⅓MHz

33⅓MHz的5倍频“衍生”为166⅔MHz

33⅓MHz的7倍频“衍生”为233⅓MHz

33⅓MHz的8倍频“衍生”为266⅔MHz

这才有了市面上主流内存产品型号中那些奇奇怪怪的频率,甚至看起来规整的100MHz也出自33⅓MHz的3倍频,一切都是33⅓MHz的衍生品。

1.5 小结

本章介绍了组成计算机的核心硬件,它们齐心协作,实现了计算机的主要功能。在时钟的“指挥”下,数据从外存进入内存,由CPU进行处理,而后原路返还。当然,数据的出发地和目的地除了外存,更有日趋多样的人机交互设备,鼠标的一次点击,屏幕上的一张图片,扬声器发出的一段音乐,这样的数据旅程。

了解硬件,是摸透计算机的第一道难关。当人们拆开计算机的外壳,盯着主板上“阡陌纵横”的印制电路和密密麻麻的电子元件观摩半晌,也很难对计算机原理产生更深的理解。即使将某个芯片暴力拆解,放到电子显微镜下,也难以理解其运行机制。

硬件是极其复杂的,其复杂程度远远超出外行人的想象,本章所述基本原理仅仅是冰山一隅。可“千里之行,始于足下”,在这基础上慢慢去拓展、去深挖,就会越来越多地了解硬件的微观原理与其参数、外形、故障等宏观表现相吻合的事情,“原来是这样”,这种恍然大悟所带来的欣喜,不亚于科学家发现自然规律时的感受。

其实,软件的本质是信息,硬件又何尝不是呢?海滩上的沙砾没有信息,有人把它堆成沙雕,有人用它做出芯片,便有了信息。金属、塑料等材料在化身为硬件的过程中并没有发生原子级的质变。当这些普普通通的原子或分子按某些规则精密地排列组合,却成了意义非凡的计算机。可如果把计算机送给一只猫,它依然没有信息,甚至还没有沙砾有趣。是人类赋予了硬件以信息,这些信息的使用者称为软件。

参考文献

[1] 英特尔®软件学院教材编写组. 处理器架构[M]. 上海: 上海交通大学出版社, 2011.

[2] 唐朔飞. 计算机组成原理[M]. 北京: 高等教育出版社, 2008.

[3] 岳怡. 数字电路与数字电子技术[M]. 西安: 西北工业大学出版社, 2004.

[4] 童诗白, 华成英. 模拟电子技术基础 [M]. 4版. 北京: 高等教育出版社, 2006.

[5] 冬瓜哥. 大话计算机[M]. 北京: 清华大学出版社, 2019.

相关图书

ChatGPT与AIGC生产力工具实践 智慧共生
ChatGPT与AIGC生产力工具实践 智慧共生
专利写作:从创意到变现
专利写作:从创意到变现
产品经理方法论——构建完整的产品知识体系(第2版)
产品经理方法论——构建完整的产品知识体系(第2版)
程序员的README
程序员的README
架构思维:从程序员到CTO
架构思维:从程序员到CTO
开发者关系实践指南
开发者关系实践指南

相关文章

相关课程