乐创DIY C语言讲义​——1.2节

1.2 计算机软件发展

计算机软件,就是我们通常意义上所说的程序。一块计算机芯片(中央处理器,CPU)被设计好之后,芯片公司会推出相应的指令系统提供给用户,以便于用户可以根据自己的需求来编写程序。这种指令系统是由芯片的架构,内核所决定的,因此可以说,只要指令系统相同的计算机芯片,就是同一架构的芯片。而这套指令系统也就是我们日常所说的汇编语言。有趣的是,计算机芯片最早是没有汇编语言这个概念的。

最早的芯片被设计出来之后,芯片公司会提供一些二进制的操作命令给用户,用户根据这些文档就可以编写出自己所需要的程序了。如,某块芯片的加法操作指令是“000b”,向寄存器传输指令是“001b”,寄存器A的编号是“10101b”,寄存器B的编号是“10110b”,指令格式是“操作指令”+“目标操作数“+”操作数。“那假设我们要把寄存器A的内容和寄存器B的内容相加,并且放到寄存器A里面。由上面的条件可以得出:相加的操作指令为”000b“,寄存器A的编号是”10101b“,寄存器B的编号是”10110b“,那么把它们按照格式编排起来就是”0001010110110b“,此时这条指令下载到计算机里面,就可以完成上述的功能。这种利用二进制编码操作的方式叫做”机器语言“。可以毫不假设地说,任何编程语言、数据库、操作系统如果需要在计算机上面运行,它们必须被转化成某个具体计算机的机器语言。而计算机刚刚发展起来的时候,存储设备也是个大问题,当时用来存储程序的主要设备是纸条,在一卷纸带上面,均匀地用针打上孔,就可以把程序记录下来了,如果程序的二进制是”1“,就打上一个孔,如果是”0“,就不打孔。打孔纸带如图1-2-1所示。

图1-2-1 打孔纸带

不难看出,随着计算机指令系统的日趋庞大,依靠二级制操作命令编程的方式已经无法满足计算机软件的发展了,因此一种更为高效的方式诞生了,这种方式非常简单粗暴。芯片厂商想到,我们可以将这些复杂的二进制命令,用另一种大家都看得懂的方式表现出来,如加法操作指令是“000b”,可以用一个大家都看得懂的英文单词“ADD“表示它,寄存器A的编号是”10101b“,可以用”RA“来表示它,同样寄存器B可以用”RB“表示。以后操作者在编程的时候,只要记住这些单词即可以了,记住单词往往比记住一串数字容易地多。这种单词在后来被称为”助记符“,这种用助记符的编程语言统称为汇编。那这个年代的程序员用汇编很容易写出上面例子中的加法程序,即”ADD RA, RB“,将这个语句输入到厂家所赠送的汇编器里面,就可以生成出”0001010110110b“这样的机器语言出来。

1969年,两个程序员肯·汤普森(Ken Thompson)和丹尼斯·里奇(Dennis Ritchie)写出了第一个版本的Unix,从此计算机软件史翻开了新的篇章。虽然新的篇章被翻开了,但是后续的操作系统移植却变成了一个非常头疼的问题,因为这个版本的Unix使用汇编语言编写的,而由于每家芯片公司的汇编语言又不一样,因此移植起来非常困难。其实在汇编语言盛行的同时,还流传着一种高级一点的语言,B语言,但B语言的无数据类型特性使得其在PDP-11机器(当时的一台小型机名称)上无法以比较优雅的方式访问字符类型,因而从1971年开始,丹尼斯·里奇(Dennis Ritchie)开始对B语言进行改造,其中最重要的是引入了数据类型的概念,这些改造最终使B语言演化为了计算机发展历史上最为重要的编程语言——C语言。到了 1973 年,UNIX 系统的绝大部分源代码都用C语言进行了重写,这为提高 UNIX 系统的可移植性打下了基础(之前操作系统多采用汇编语言,对硬件依赖性强),也为提高系统软件的开发效率创造了条件。可以说,UNIX 系统与C语言是一对孪生兄弟,具有密不可分的关系。

图1-2-2 肯·汤普森(Ken Thompson)和丹尼斯·里奇(Dennis Ritchie)

目前,操纵系统已经深入到我们生活的方方面面,如智能手环上面的RTOS(实时操作系统),智能手机上的安卓或者IOS,办公时候的Windows等。但是,正如我们上面所说,这些硬件不用操作系统也可以正常运行,为何一定要加入操作系统这一个额外的软件在上面呢?有人可能会说,没有操作系统就没有了这些漂亮的UI界面了。关于这个回答肯定是不对的,早期如我们玩的游戏机,如黑白机等,他们是没有操作系统的,仅仅靠一些C语言代码运行在一些内存较低的8位CPU上面,还是可以做一些那个年代值得惊艳的界面。引入操作系统的原因,我总结了一下:

(1)、CPU硬件性能的增强,需要有一个强大的管理软件来调度,使得硬件性能不被浪费;

(2)、计算机外设的增多,需要有一个强大的系统软件把这些驱动程序高效、安全管理,并为应用软件提供标准统一的接口;

(3)、内存管理与虚拟化,可以将多个应用程序同时独立地运行在计算机上。

(4)、出于安全的考虑,需要将物理硬件和应用软件隔离开,之前我们说到,C语言是可以直接操作硬件的,且没有一些高级语言的内存管理器,如果不用操作系统隔离开,某些程序员用C语言这样的语言编程引发的内存泄漏将会引起硬件错误。

也许20世纪70年代注定是计算机历史上知识大爆发的时代,因为此时,不仅出现了Unix操作系统,还出现了首个计算机网络,即后来的“英特网”。而Linux操作系统设计的初衷,就把强大的网络功能嵌入到整个操作系统的设计中来了,以至1983年,Unix商业化之后,此后8年时间内,一直没有可以与之媲美的操作系统出现。说到Unix系统的商业化,这里也有几个小故事。Thompson 在1975/1976学年来到了加州伯克利分校做客座教授,并且带了些研究生一起继续进行Unix的后续开发,在伯克利,很多新的特性加入到了Unix操作系统中,并发布了一些早期的BSD版本。BSD (Berkeley Software Distribution)是由加州大学伯克利分校基于Unix发布包进行二次开发和发布的。BSD为Unix带来了很多的新的特性,特别是1983年发布的4.2版本的BSD,该版本实现了TCP/IP协议栈。而与此同时,Unix逐步走上了闭源的商业化之路,收费的Unix也被称为System V。而流传于伯克利大学的BSD却依旧保持着独立的开源化发展,由此以后,原本的BSD Unix走上了独立的发展之路,先后发展了OpenBSD,FreeBSD,NetBSD等众多版本,为后续的自由软件运动,注入了一些Unix的基因。这里再说一点,很多商业软件也是基于BSD 开发的,比如苹果的IOS。

Unix离普通人越来越远,高昂的价格不仅让很多公司望而止步,连大学生学习操作系统原理也没有一个可以讲解的对象了,因此中途还诞生过一个叫做“Minux”的操作系统,由Minux再发展,也发展出了一个独立的类“Unix”分支。后面1985年以后,自由软件运动像宗教运动一样在全球蔓延开来,也诞生了后来的Linux,这部分历史可以单独写本书,这里就不再赘述,有兴趣可以自行查阅资料。

上面的内容,详细阐明了C语言和Unix的诞生,而80年代还诞生了一个具有划时代意义的东西,那就是个人计算机,又称为IBM PC,IBM微机的诞生,标志着计算机从科研工具走向生产力工具甚至娱乐工具。此后所有的计算机都与其相兼容,被称为“IBM XT/AT兼容机”,这一部分市场到后来逐步形成了Intel硬件加Windows操作系统的标准计算机。从这时候开始,计算机迅速普及,人们对计算机的内容需求越来越多,如游戏,新闻,影音等,这就使得操作系统越来越庞大,应用软件的创作越来越高。再到后来,想要从0到有开发出一个软件,基本变得异常困难,而此时的C语言虽然有标准库的支持,但是面对如此多的应用软件需求,着重于面向过程操作的C语言用来做应用软件开发,显然有些力不从心了。

后来的软件行业,一个新的名词诞生了,即“面向对象”。“面向对象”的三大特征就是抽象、继承、多态,这里我们不解释这三个名词,大家只需要知道,“面向对象”编程可以使得编程变得简单,明了。由于这个思想的诞生,90年代以后,一大批优秀的专做面向对象编程的语言兴起了,其中最具有代表和用户最多的三种为C++,C#,Java。C++和C#,Java虽然都是为了面向对象设计的语言,但C++一般都被看作是C语言的一个扩充版,最典型的就是指针的使用可以操作任何资源,再加上C++比C语言更复杂的规则,使得其非常难用。而C#和Java虽然也是在C++的基础上发展起来的,但是它们完全摒弃了C++的硬件粘合性,它们更容易看作是运行在某个软件上面的编程软件,如C#必定是基于某个.net平台运行的,而Java也是运行在JVM(Java Virtual Machine)上的,这些语言编译之后生成的也不是直接的二进制,而是某种中间语言,运行时,它们的虚拟机平台再这种中间语言翻译成机器语言去执行。同时,使用C#和Java根本不用担心内存溢出问题,这些虚拟机上面都有GC(GarbageCollection)机制。比较有意思的是,C语言虽然比C++早,但是它的热度远远高于C++和Java。图1-2-3展示了2020年6月年世界流行的编程语言排名。

图1-2-3 2020年6月年世界流行的编程语言排名

(0)

相关推荐