19
8 月
PC通识3:标准PC软件篇
- By IanGoo
当我们在讨论“标准PC”的时候,讨论的不仅仅是硬件,还有在硬件基础上建立起来的软件及其生态。
在很久以前,计算机教材和书籍会简单地将软件划分成“系统软件”和“应用软件”两大类。但是,当我实实在在地用了多年的PC之后,我意识到了这样一个事实:软件的分类远比这要复杂得多;甚至软件和硬件之间的界限都并没有那么泾渭分明。
所谓的“软件”,有这么一种说法:凡是能看得见、摸得着的,都是硬件,反过来,看不见(代码不算)、摸不着的,那就是软件。但是其实并没有那么简单。比如,这个东西:

学过数电的都能认出来,这玩意儿是个一位全加器。如果有动手能力的话,完全可以手焊一个出来。这东西就是一个“能够执行特定任务的硬件电路”。
那么问题来了,它是硬件还是软件(或者说程序)?
说它是程序吧,这东西是一堆肉眼可见的二极管和三极管就能做出来的;说它不是程序吧,它的表现和和这段代码又一毛一样:
def adder(a,b)
c = a + b
return c
就是定义了个加法嘛……
这就是一个很典型的游走在硬件和软件模糊地带的东西,将这种东西的规模继续放大成千上万倍的话,前文中提到的“指令集架构”(ISA)和它也是一个概念——它是可以执行特定任务的硬件电路。
所以,这里可以提一下我对程序的理解——程序是一种控制范式。它可以是某种抽象的概念,也可以是某种硬件的排列组合方式。这种理解的语言描述当然是不准确的,但是却可以用来说明最早的“程序员”们的工作方式。那还是在二战刚刚结束的1940年代。横空出世的ENIAC开启了图灵完备电子计算机的时代。但是——当这样一台计算机摆在你面前的时候,你应该怎么去使用它呢?
作为21世纪的计算机用户,我们无疑是幸运的。只需要打开它,想要干什么——不论是编辑一些文本资料,还是听音乐、看视频,都有现成的软件可以调用。而在1990年代之前,计算机用户那是人均程序员。

这是Commodore PET启动之后看到的界面,看到开头的“BASIC”,也许有人会认识这五个字母——这不是“基本”的意思,虽然这里有双关梗。BASIC的含义是“Beginner’s All-purpose Symbolic Instruction Code”(初学者通用符号指令代码),这是一种相当流行的入门型程序语言。所以,Commodore PET一开机,就让用户自己写程序?
还真是。甚至在当时的一些电脑杂志上,也会有大段的代码,用户只需要将这些代码输入到BASIC环境,就可以直接运行这个程序。

需要用什么软件现写,可以。很硬核。但是和1940年代的先驱相比,他们还差得远。

ENIAC完工之后,美国军方专门招募了几位心灵手巧、心思缜密的女性来操作这台庞大的机器。当科学家们需要计算点什么东西的时候(通常来说是算一些和氢弹相关的东西),他们得先将算式进行拆解,拆到能够用ENIAC的那一堆电子元器件能计算的程度,然后给出接线图,由这几位女性程序员将成百上千根线缆插到密密麻麻的操作面板插头上,将各个继电器开关的初始状态挨个确认好,然后通电,开始算。
这就是最早的电子意义上的“编程”——硬件意义上的“编程”。实际上,如果用现代意义上的CPU来类比,就是科学家们设计了一个CPU指令集,然后由这群女士手搓了出来。
这样的“软件”,足够硬核。更硬的恐怕得继续往前到机械计算时代的那位传奇祖奶奶了。
相比之下,我们今天的用户简直就是一群废物。想要计算两个数相加之和,都要考虑打开一个软件——不管是系统自带的计算器,还是GeoGebra(杀鸡用牛刀)、Excel(杀鸡用榴弹炮)、或者Mathematica(杀鸡用弹道导弹)。但是也正是这样一层层的抽象和封装,让多达数百亿个晶体管的庞然大物能够被普通人以一种简单、友好的方式使用。这种抽象概念起源于冯·诺依曼在ENIAC之后创造的EDVAC,这是一台遵从冯·诺依曼提出的普林斯顿结构设计的计算机。普林斯顿结构不仅提出了计算机的结构,还有一个特征:程序与数据统一存储。今天,我们在一台Windows PC当中很随意就能找到一种后缀为.exe
的文件,他们和你写出来的.docx
文档都保存在硬盘当中,都是以文件的形式存在的。但是它却是一段程序。它可以读入内存后进而进入寄存器之后,控制CPU的行为,完成特定的任务。
这一层层的封装,里面就少不了我们平时接触到的各种特殊的软件。比如固件、BIOS、驱动程序、操作系统,在这一系列支持之下,我们才能愉快地运行各种应用软件来完成自己的事务,或者很简单地给自己找找乐子。
我们首先介绍最接近硬件层级的软件,这种特殊的软件被称为“固件”(Firmware)。
固件
固件之所以特殊,是因为它通常是被以一种硬件方式写入到一种特殊芯片上的。
之前,我们介绍过内存的英文缩写叫“RAM”,Random Access Memory,特点是断电就把一切忘记。在计算机系统当中还有一类存储芯片,叫“ROM”,Read-Only Memory,只读存储器。它和RAM相比是另一个极端,断电不会丢数据,但是也没法轻易修改里面的数据,通常需要用一些特殊的工具或者工作模式才能改写其中的内容。这种被固化在ROM当中的程序通常是操纵硬件的最底层的代码。
几乎每一个硬件都有对应的固件,小至蓝牙耳机,大至——那就说说PC里最大的那块电路板吧,主板的“固件”,它有一个特别的名字——BIOS。
BIOS
BIOS是“Basic Input Output System”(基本输入输出系统)的缩写。最早出现在1975年的CP/M计算机上。这一概念在后来IBM开发万恶之源(bushi)5150的时候沿用了过来,并且还成了IBM和一众兼(shan)容(zhai)机打口水仗的热点。既然万恶之源都用了BIOS,那现在的徒子徒孙也免不了继续沿用这样的设计。
BIOS通常是一台PC通电启动之后加载运行的第一个软件。它会完成这样的一系列事务:
- 首先,扫描并检查全部或者部分硬件,确认它们都还是活着的。这一阶段被称为POST(Power-On Self Test,通电自检)。
- 根据启动优先级寻找操作系统引导(Boot Loader)。如果找到则执行下一步,如果找不到的话,早期的电脑会进入主板上另一个ROM内建的BASIC环境,现在的电脑则直接弹出一条:No bootable device found的错误信息,或者直接进入BIOS设置界面。
- 找到Boot Loader之后,CPU寄存器和内存初始化完成,开始读取操作系统。
- 操作系统加载完毕,从BIOS手中接管硬件I/O权限,BIOS的任务完成并关闭。
当然,这是很基础的BIOS功能,一个现代高端主板上的BIOS系统能提供的功能远比这些最基础的启动相关事项要复杂得多,比如风扇转速控制、RGB灯光接口、CPU的fTPM信任计算模块、CPU和内存的超频等等,都可以在BIOS当中完成设置。

早期的BIOS有诸多缺陷和限制,如它本身只是一个16位的程序,只有1MB的内存寻址空间,它也只能兼容MBR磁盘分区表,而MBR有一个致命缺陷——超过2TB的磁盘就不认了。随着硬件的飞速发展,古旧的BIOS规范已经不再能胜任新的要求,因此在2006年,一个新的规范标准开始推行,这就是UEFI(Unified Extensible Firmware Interface,通用可扩展固件接口)。UEFI可以完全支持64位系统和64位内存寻址、能够支持GPT磁盘分区表(最大可以支持到9.44ZB,翻译翻译,就是9.44×1024×1024×1024TB的容量)。另外,UEFI的设置界面也不是上面BIOS那种让人看着脑壳痛的蓝底白字的古旧风格,而是可以做得更加现代,甚至能在里面用鼠标。

掌握BIOS的设置可以完成很多很底层的设置,不过,这往往也是相对高端的技能。我们之后或许会对它进行一个简单的介绍,现在如果想要进去看看的话,可以翻阅自己机器的说明书或者主板的说明书,一般都是在刚启动的时候就狂敲键盘上的某个键(比如Del
、F2
之类)。注意,如果看不明白里面都是些啥的话,不要轻易更改里面的任何设置,看看就好,原样退出就行。
现代主板的BIOS通常不再是以ROM作为存储介质,而是换成了闪存——类似于U盘的存储芯片。这主要是因为现在的主板BIOS时常需要根据新的硬件、新的标准来更新。真正的ROM写入起来非常麻烦,需要使用专门的设备,通过更高的写入电压将程序“烧录”进去,使用闪存芯片就很简单了,普通用户无需任何额外设备,找个U盘装上厂商提供的新版BIOS文件,然后进到主板的一个特殊的工作模式,插上U盘就可以很轻松地更新BIOS。
固件是一类和硬件紧密相关的软件,我们在日常使用PC的过程当中应该也听说过一种有些类似的东西——驱动程序(Driver),也是和硬件紧密相关的。
它们又是什么?
驱动
在计算机领域当中,“Driver”是一个比较宽泛的概念。“Driver”在字面意义上指的是司机。如同一辆汽车需要有司机驾驶才能走起来一样,一个底层的概念也需要一个特别的程序“带动”才能更好地运转。比如“数据库驱动”,它就是将数据库抽象出来,为外部程序提供接口、访问规范等属性的程序。而多数情况下,当我们讨论“驱动”的时候,指的是“设备驱动”。它也是一个抽象的程序,软件可以通过驱动程序来更好地控制对应的硬件。
举一个很简单的例子:USB。USB定义了不同引脚的不同电平和信号序列,以和外部的设备进行通讯,经过驱动程序的抽象,这些最底层的概念:什么引脚以什么电平传输什么状态的电信号都被隐藏了起来,而是提供了更高级、更抽象的接口:设备检测、数据传输、电力传输等,操作系统通过USB向U盘写入数据,只需要告诉USB驱动“我要传输数据”,USB驱动随后便会将这样的高级需求转变为更底层的动作:某对引脚以什么样的频率传输高低电平。
基本上所有的硬件都需要驱动程序的配合才能正常运转。也许这时候就有人会反驳了:可是我刚装完Windows的时候,已经有很多硬件是直接能用的啊?甚至显示都没有问题。
这主要是因为,能够被普通消费者直接接触到的操作系统,特别是Windows和多数成熟的Linux发行版,都已经自带了一些驱动。但是很容易理解,由于涉及到硬件的设计,通常情况下,只有硬件的制造商有能力提供对应硬件的驱动程序,或者他们提供的驱动才是效率最高的。一些非常通用、标准化程度非常高的驱动,可以直接使用操作系统自带的,如USB驱动。一些相对专有、但是遵从某些特定底层标准的硬件,在系统自带的通用驱动程序下也能用,但是效率不高,比如显卡驱动。系统自带的显卡驱动只能提供最基础的显示功能,甚至分辨率的支持都不完全,要能够让显卡能够火力全开运行游戏和大型3D软件,还是得安装对应的GPU制造商提供的显卡驱动;还有一些比较少见的硬件,操作系统是没有自带驱动的,这就必须得安装对应的专有驱动才能运行得起来。
操作系统
这算是到了多数人都会接触到的领域了。
操作系统(Operating System,OS)是一种底层系统软件,它负责管理、调度计算机的软硬件资源、提供一些通用的服务。
我们回过头,看看ENIAC的操作员女士们——很显然,在普林斯顿结构尚未成型、计算机都没有“指令集架构”的时候,计算机当然更是没有“操作系统”的概念的。一切的硬件调度都需要在计算之前预先设计好。随着技术的进步,普林斯顿结构开始出现,计算机开始可以储存程序,但是需要用到哪些资源,依然需要预先调配好。比如一个程序需要4bit的寄存器,就得真的将4个bit的寄存器预备好。计算机需要哐哐哐输出一堆打孔纸带,那么操作员也需要将打孔纸带给它装好。
很显然——还是麻烦。于是1966年,IBM开发了划时代的System/360计算机系统。IBM为它专门开发了一套软件系统来负责系统的资源调度,这就是世界上最早的电子计算机操作系统——OS/360。
今天,操作系统广泛存在于一切计算机设备当中,包括手机。在PC领域,最成功的操作系统当然是Microsoft Windows。

但是除了Windows之外,还有一些其他的操作系统可供选择。比如,如果你是苹果电脑的用户,你大概率用的是macOS操作系统。
在这两个市场占有率最高的操作系统之下,还有一个庞大的操作系统家族——GNU/Linux发行版。

Windows和macOS都属于闭源、收费的商业操作系统,而GNU/Linux绝大多数都是开源、免费的操作系统。
那照理说,最流行的应该是Linux才对啊?为什么是Windows呢?
一个操作系统能否流行开来,一个很重要的因素是对应的生态环境是否成熟完善。用户使用PC从来不止是操作系统,而是运行在其上的各种应用软件。但是这里就有个问题:我们拿到的软件,通常都是二进制分发,软件的“安装”仅仅是将一系列已经编译好了的二进制文件复制到本机硬盘上罢了。而不同操作系统之间的二进制格式通常情况下都是互不兼容的。这就意味着,软件开发者要么提供源代码,要么就得提供对应操作系统上编译的版本才行。对于市场占有率很高的操作系统比如Windows而言,各大软件商都会毫不犹豫地提供支持,但是一些很小众的操作系统,软件商就有可能直接放弃了。而软件支持广泛,本身就是一个操作系统能够流行的前提。假以时日,这种马太效应就会形成巨大的市场惯性。
当然,Linux自身的问题也是不可忽视的。
从硬件一路说到操作系统,我们大至可以理出这样的逻辑结构:

这就是今天使用计算机的方式:上层抽象下层,上层操作下层,最终到应用程序为用户服务。正是这样一层层的“抽象”,让计算机变得如此易用,甚至最终进化成了老人和小孩都能用起来的智能手机的形态,这也是促成计算机高度普及的重要因素。
但是,易用性做到了手机这样的层级之后,也让用户彻底失去了探索“计算机是如何运作”的可能性,所以在需要用户知道“计算机是如何运作”的PC领域,越来越多的用户、特别是本应当在学习能力巅峰的年轻用户,对PC表现出了远远超出上一代人的陌生。而这也是我想写《PC通识》系列的原因。
说回到标题,我们正在讨论的是啥叫“标准PC”,前面已经探讨过了“标准PC”的硬件形态,这篇探讨的是“标准PC”的软件环境。算是简单介绍了一下“标准PC”是个啥。
下一篇,我们将扮演一名普通的消费者,来模拟一下:如果我要购买一台PC,我应该如何思考和决策?