代码改变世界

老赵书托(3):深入理解计算机系统

2009-11-23 00:10 Jeffrey Zhao 阅读(...) 评论(...) 编辑 收藏

这次我要推荐的是《Computer Systems: A Programmer’s Perspective》(下文简称CSAPP),在国内可以买到其影印版。它也已经被翻译成为中文,即中国电力出版社的《深入理解计算机系统(修订版)》。

基本知识

如果说我上次推荐的SICP强调的是编程能力,抽象能力的话,那么CSAPP这本书强调的便是作为一个程序员的基本知识。SICP来自世界顶级学府MIT,而CSAPP也同样出身名门:CMU(卡耐基梅隆大学)。虽然没有SICP那么历史悠久,但它被世界几百所大学(幸运的是也包括我所就读的复旦大学)用作教材也有好多年了。

这本书的中译名为“深入理解计算机系统”,我非常,十分,以及百分之一百二十地不满意。我这么说的原因在于这个译法完全扭曲了书的本意。如果直译原书名,应该是类似于“以程序员的视角理解计算机系统”,何来“深入”二字。可能在国内编辑看来,这是讲系统的,用C和汇编语言的,因此很“深入”,但我认为这只能说明国内技术氛围的浅薄。因为事实上,这是一本入门级别的书,这本书其实并不“深入”,它谈论的内容还是相对比较浅的。但“浅”不代表“浅薄”,写一本面向初学者的好书往往是非常困难的,因此无论是SICP还是CSAPP,它的作者都是顶尖学府的教授,结合多年教学经验而写出来的。

CMU把这本书作为“Introduction to Computer System”课程的教材,是面向计算机专业低年级学生的“计算机系统介绍(导论)”,可能这些学生只是刚刚了解如何使用一门高级语言——如Java进行编程,对于计算机系统的工作方式等话题可谓一点都没有接触过,而CSAPP对读者的背景也只要求是“一些编程经验”而已。这本书的话题覆盖面很广,从计算机的基本组成,二进制数据表示方式,到机器级别的指令,CPU工作方式,存储结构和优化,操作系统的虚拟内存管理,程序运行方式,I/O,网络、到(较底层)程序性能优化和并行程序开发等等。所以,它其实覆盖了“计算机组成原理”,“操作系统”等许多课程的内容,其中的许多话题都能再次展开,继续深入,都能再变成一本,甚至N本经典。事实上,在高年级的计算机专业课程设置中,都会有更加纵向的内容出现。

因此,如果有人说它“底层”,我同意。但如果说它“深入”,至少我不那么赞同。

“覆盖面广”,其实就是这本书的最大优点。它告诉我们计算机是如何设计和工作的,操作系统有哪些重点,它们的作用又是什么。CSAPP的目标其实便是要讲清楚原理,但并不会把某个话题挖掘地过于深入,过于细节。例如书中第4章使用了自己“设计”和“实现”的“Y86”处理器架构,便是为了简化X86指令集,使课本内容在能够说明问题的前提下也不至于太复杂。因此,读完(其实也并不一定要读完,说实话我也没有读完)这本书后,我们就可以对计算机系统各组件的工作方式有了理性的认识。

那么,这本书适合什么人阅读呢?对于这个问题我也有过犹豫。在打算写“老赵书托”系列的之后,前两本列在书单的上便是SICP和CSAPP。我对CSAPP推崇备至,在以前的几篇文章中也都有提及,但最后还是先推荐了SICP。怪怪同学当时在回复中说到“我还以为你会先推荐CSAPP”,其实这就是因为一个“适合面”的问题。在我看来,SICP所强调的编程和抽象能力是任何程序员都需要的,但是如果您问我“所有程序员都应该读CSAPP吗?”,或者再具体一些:“前端JavaScript程序员需要看CSAPP吗?”,那么我可能就无法给出100%令人满意的答案了。我可能会这样回答:其实这些内容很多时候并不一定可以“直接用于”某个工作,但是它其实和操作系统,编译原理等话题一样,包含的是一套“工作方式”,“算法集”,“实践成果集”,其中很多理念,如Cache Hierarchy,Copy on Write等理解的适用范围其实都是非常广泛的。在一定程度上,其实它和SICP一样也是在锻炼思维方式,只不过是已经经过具体化的实践方式而已。

因此,即便你是一个前端JavaScript程序员,也可以从CSAPP这本书中获益。如果您是.NET程序员,那么您更加适合看这本书了。说一句“豪情万丈”的话:如果不知道XX,YY或ZZ的话,这如何算是一个优秀的程序员?这本书和平时的工作可能的确不一样,相比起来“底层”了一些,但是它还是会把“底层内容”控制在一定深度之内,而不会讲某个具体话题挖掘到“事倍功半”的程度。而事实上,虽然在进行.NET开发的时候我们已经在一个较高的抽象上工作了,但是我们的程序还是运行在操作系统上,还是在遵循着某个规律在运行着,了解一些内部的工作机制也有助于我们写出更好的应用程序。

说来也奇怪,虽然各种语言,框架发展地越来越好,按理来说我们写程序也应该越来越容易。但是现在看来,一些基础性的内容反而也变得越来越重要了,例如在并行计算面前,计算系统的一些细节,如内存一致性模型,线程调度,程序的局部性(Locality)又被提上台面,否则我们很难写出高效的应用程序。同样,一些如函数式编程,Monad等在几年前看起来十分科研型,数学化的事物也离我们越来越近了,如LINQ,Reactive Framework等等,其实它们都已经是我们身边的事物了。

阅读建议及相关资源

CSAPP这本书覆盖面很广,我认为并非要一字不漏地读完才行。根据我的个人观点,我们应该着重阅读书的第1章“A Tour of Computer Systems”和第一部分“Program Structure and Execution”(从第2章开始,大约占据了书中一半篇幅),其中包含了数据的机器级别表示方法,汇编语言和执行方式以及CPU架构方面的内容,我们应该关键性地理解其原理。如第6章“Optimizing Program Performance”提出了许多种机器级别的优化方式,在现在看来,其中的某些方式过于细致,乃至在实际工作过程中已经不再推荐了(如内联一些方法以提高性能),我们要在把握住“为什么”而并不是单纯的吸收“怎么做”。对于书中的第二部分“Running Programs on a System”主要讲述的是操作系统方面的内容,可以读得略为简单一些,但其中的第10章“Virtual Memory”,它谈论了操作系统中虚拟内存机制的各个方面,非常关键,需要细读。至于书中的第三部分“Interaction and Communication Between Programs”便可以更加“选择性”地阅读,我只阅读了第13章“Concurrent Programming”,而其他两章都只是简单地扫过而已。

作为经典的教材它一定有许多附加资源,例如在它的官方站点给出了一些链接,其中最关键的可能是学习者站点,其中包括这本书所需要的各种工具,参考文档等各种资源。从网站上也可以了解到,CSAPP即将在2010年2月份推出第2版,根据近几年的发展做出了不少改进

不过,在这里我要着重推荐的是接下来的内容:我的大学时代就读于复旦大学软件学院,属于教育部35所实验性软件学院,学费比较昂贵——幸运的是,我所接受的“实验性教学”使用了一种比较“西化”的方式,无论是课程设计还是教材都比较“与国际接轨”。例如和爱尔兰都柏林大学合作办学,有些课程由老外来教,同时也会接触一些“函数式编程”等国内较少接触的内容。大二的“计算机系统导论”课程便参考了CMU的ICS这门课,教材自然就是CSAPP这本书。在我印象中,每年最热闹的课程便是大二的这门必修课(高年级所开设的“计算机组成原理”,“编译原理”、“计算机网络”等就是“方向性”课程,并非人人必修),尤其是做一些大作业的时候,在BBS上便会讨论的非常热烈(不得不承认,“拆炸弹1”等实验也特别有趣),而每年此时也往往会诞生出一些“牛人”,基本上都是些“前途似锦”的人物,大都即将或已经在世界顶级学府深造,令人难以望其项背。而在两年前,这门原本是一个学期的课程,也已经变成了为期一年的课程,这也说明了ICS的重要程度。现在这门课已经成为了复旦大学的精品课程之一:“计算机系统基础”,我们从网站上可以下载到所有的PPT,练习和解答等内容,甚至还有视频下载。希望这些内容能够对您有所帮助。

上次我也提到北大使用SICP的课程:“程序设计技术和方法”。其实现在国内有很多大学都在使用世界一流教材,希望也会有越来越多公开的内容。

扩展阅读

在这里我想可以再提及两本书,一本是之前所提到的国产书精品《链接、装载与库》。这本书主要讲解了编译过程中的“生成文件”的过程,以及应用程序执行时文件是如何被操作系统加载的,并且同时涉及到Linux和Windows两个平台。实话说,这些内容并对我来说并不是些必须了解的内容(相信对大部分同学也一样),因此我把它当作一种“扩展阅读”以及“知识巩固”。

对于这种类型的书,我有自己特殊的阅读方式,那就是“快速浏览”。例如,对我来说,我可能更需要知道链接是做什么用的,一个可执行文件或一个动态链接库文件大致组成有哪些,加载时各段的作用是什么等等,但我不需要具体了解每个段的布局,文件头的具体格式,占多少字节等等。因此,我更关注的可能是其中的示意图,而对于其中一些和具体数据相关的表格和代码就匆匆掠过了。这本书我“翻”得很快,大约只用了4、5天,我想等我真需要这些内容的时候再回头细读吧。有朋友说,更值得一读的是著名的《Linkers and Loaders》,但这部分话题对我来说实在有些距离,我还是从更容易接受的《链》来接触吧。

说来有意思,我建议您在读《链》这本书的时候,着重关注“链接、装载与库”的部分,而是那些少量的,如操作系统的线程和内存管理方式,甚至于附录中有关“字节序(Byte Order)”的内容。因为它们往往是书中主要内容的基础,拥有更广的适用性。

而第二本书“顺便提及”的书是《Windows Internals 5th Edition》,人民邮电出版社已经引进了其影印版(而且影印质量好的令人发指,我仔细对比之后发现,除了不是硬皮之外,从纸张和文字几乎和原版一模一样)。这的确是本“深入”级别的书,基本上覆盖了Windows内核的方方面面,包括系统架构,内存管理,线程调度,安全机制,文件系统等各种话题,对于我们Windows平台上的程序员,这方面内容可能更有针对性。

不过说实话,我刚刚购入这本书,更别提仔细阅读了。不过我看过这本书第4版中文版的大部分内容,它由潘爱民老师翻译,应该说翻译地很不错。如果您对英文的接受程度不高,也可以从中文版入手。不过第5版覆盖了Windows Server 2008和Windows Vista,直接增加了200多页的篇幅,还加入了Superfetch、BitLocker和Hyper-V相关的内容,可谓是一次重大的升级——其实这其实也可以看出Vista的相对于XP,在内核级别有了很大改进。而目前Windows Internals第6版也在写作过程中,其中包含Windows 7和Server 2008 R2的内容。我本以为Win 7的内核改进不大,但是从近期的PDC大会上发现似乎也不能这么说

Windows Internals一书的主要作者之一是Mark Russinovich,这位和基努·李维斯有几分相像的帅哥除了是Windows NT内核专家,微软Technical Fellow之外,还是著名的Sysinternals工具包的作者。Sysinternals工具包可谓Windows程序员居家旅行,杀bug灭口的必备工具,因此Windows Internal的重要特点之一便是用Sysinternal中的各种工具来进行“实验”,这也给这种有深度的书带来了相当的实践性。在我看来,这本书虽然深入,但并非是“枯燥”理论,还是一本写得比较“好看”的书。

说到“好看”的技术书,那么我还是以CSAPP这本书中“致谢”部分的最后一句话来结尾吧:

Finally, we would like to acknowledge the great technical writers Brian Kenighan and the late W. Richard Stevens, for showing us that technical books can be beautiful。

如何把技术书写的“好看”,真是门艺术。

相关文章

 

注1:“拆炸弹”是ICS课程的配套实验之一,它的主要工作便是通过将一些小程序(即“炸弹”)反汇编后阅读其汇编代码,然后通过在程序运行时输入特定的字符串来“拆除”炸弹。有些炸弹可能只是输入某个特定的字符,而有些炸弹可能需要输入复杂的字符串,通过“内存溢出”来覆盖掉堆栈中的特定内存(如return address),以此改变程序运行的“轨迹”。整个过程非常有挑战,但也很有趣味。能设计出这样的实验的确令人敬佩。