Preface 前 言
为什么要写本书
在做云计算时,某天我突然兴起,探究了一下QEMU的作者,当时非常好奇是什么人能写出这么强大的融合计算机软件和硬件的作品。那是我第一次知道计算机奇才——Fabrice Bellard。除了QEMU, Bellard还开发了大名鼎鼎的被称作音视频领域 “瑞士军刀”的FFmpeg,编写了编译器TinyCC和3D渲染引擎TinyGL。此外,他仅用10个月的时间就实现了一个软基站。Bellard的著名作品不胜枚举。
Bellard的触类旁通能力令人叹为观止,有人说他一个人就可以抵得上一个精英团队,这种能力与他对计算机本质的理解是分不开的。在Andy Gocke和Nick Pizzolato写的关于Bellard的一篇小传中提到,Bellard认为学习计算机最重要的两个方面是研究计算机是如何工作的以及对计算本身的研究。
Bellard放在第一位的就是学习计算机的基本工作原理。Andy Gocke和Nick Pizzolato认为,Bellard自9岁就开始使用类似机器代码的语言编程,后来逐渐扩展到高级语言,这种学习经历使他对计算机原理的理解非常深刻。时至今日,Bellard依然认为有抱负的计算机科学家必须通过学习汇编语言以及计算机硬件来深入理解计算机的工作方式。
要理解计算机是如何工作的,没有什么是比写一个操作系统更好的方式了。通过动手编写操作系统,我们可以深刻地洞悉计算机的运行原理。在深刻理解计算机的运行原理后,在编写程序时,我们的思路将不再局限于使用语法表达逻辑的层面,而是能够站在计算机的角度思考,每写出一行代码,都能清楚每一个变量在内存中是如何分配和存储的,以及在计算机系统的各个部件间是如何流转的,从而理解每一个计算是如何完成的。这不仅对开发操作系统本身有意义,还可以使我们在全栈开发中写出高质量的程序。
回顾我自己的经历,我曾经认为汇编、微机原理等在编程中根本用不到,所以简单地应付考试了之,没有深入理解相关内容。之后我花了大量的时间来学习各种编程语言的语法,但还是常被各种纷繁复杂的“语法糖”绕得晕头转向。直到自己动手写操作系统,因为需要而逼迫自己学习汇编,我才越来越深刻地体会到,如果基础打得好,根本不需要耗费那么多时间去学习那些语法。我们在大好的青春年华中本末倒置地花费了太多时间去学习表面上的东西,花了太多的时间在语言层面兜兜转转,而没有触碰本质。
在这些年的探索过程中,我发现很多计算机领域的著名人物都是很小就开始学习计算机,他们都是在学生时代参透了计算机的本质,在年富力强时开始产出。而我们则更多是在年富力强时才懂得并且开始学习,虽然也很勤奋努力,但事实上起步晚了若干年。虽然我们现在也开始提倡青少年学习编程,但是基本还是在学习语言,而不是学习深层次的计算机工作原理。
于是,在我自己的孩子过了9岁时,我就开始让他接触计算机,首先让他从了解计算机的基本原理开始,然后学习汇编语言和高级语言,最后带着他动手写操作系统。我希望他在学习知识的黄金时期,能正向地学习计算机,悟透计算机的本质,而不要再重复我在探索过程中走过的各种弯路,少浪费青春年华。
我们想将这些经验分享给所有学习计算机的人,于是就有了今天这本书。
本书读者对象
少年强则国强,青少年是我国计算机发展的未来。本书刻意兼顾了青少年的知识储备和理解能力,希望能帮助他们深入了解计算本质,而不仅仅是浮在编程表面。
对于正在学习或者准备学习操作系统技术的大学生来说,这本书可以作为操作系统课程的实践教材。他们可以结合书中内容自己动手实现一个完整的操作系统,以对抽象的理论知识有一个感性的认识。这本书也可以作为汇编语言以及C语言的实践教材。
对于软件研发相关的从业人员来说,这本书可以帮助他们深刻地理解计算机和操作系统的原理。无论是应用软件开发人员,还是中间件以及操作系统底层开发人员,要想成为一名合格的程序员,深入学习操作系统技术是必不可少的。
最后,这本书写给所有想了解计算机如何工作以及所有和我一样怀揣操作系统梦的操作系统爱好者,希望这本书能让他们顺利地穿越操作系统迷雾,深刻领悟计算机工作原理。
如何阅读本书
本书从逻辑上可以分为上、下两篇。上篇(第1~5章)首先讲述了计算机的基本原理,从电子计算机如何使用电进行计算开始,讲述了电是如何抽象为信息的,处理器是怎样进行运算的,内存是怎样存储信息的,处理器和内存是如何通过总线通信的,处理器又是如何访问外设的,等等。接着讲述了这些部件是如何结合起来运行程序的。
然后从机器语言开始讲起,通过使用机器语言编写程序,帮助读者深刻理解指令和程序。接着讲述了汇编语言和C语言。第4章结合汇编语言讲述了计算机体系结构。第5章从C编译器如何将C语法翻译为汇编语言的角度入手,聚焦于语法后面的本质,希望能让读者彻底地理解C语言,而不再纠缠在指针等复杂的语法上。
下篇(第6~14章)从0到1实现了一个操作系统。我们从引导开始讲起,然后阐述了内存管理、进程、中断和异常、进程调度、系统调用、进程间通信,最后实现了显示器上的字符和图形输出以及从键盘接收输入。除了从应用程序直接访问内核外,下篇还展示了什么是C库、图形库等,以及从应用程序到C库、图形库,最后到内核的完整软件栈 。
勘误和支持
由于水平有限,加之编写时间仓促,书中难免出现一些错误或者不准确的地方,恳请读者批评指正。
王柏生
2023年5月