最近重读了《深入理解计算机系统》这本书,英文名叫Computer Systems: A Programmer's Perspective,简称CSAPP。
第一次读这本书是在大学的时候,那时候很多地方看不懂,只是囫囵吞枣地读了一遍。工作了几年之后,有了一些编程经验,再回头读这本书,发现很多之前不懂的地方现在都懂了,而且越读越觉得这本书写得好。
这篇文章,我想分享一下读这本书的读书笔记和感悟。从计算机系统的整体架构到具体的实现细节,从程序员的视角理解计算机系统,聊聊这本书为什么是计算机基础领域的必读书,以及如何读好这本书。
先说明一下,我读的是第三版中文版,由机械工业出版社出版。不同版本的内容可能会有差异,但核心思想是一样的。
这本书讲了什么
先简单介绍一下这本书。
《深入理解计算机系统》是由Randal E. Bryant和David R. O'Hallaron合著的,两位都是卡内基梅隆大学的教授。这本书最初是CMU计算机系的教材,后来因为写得太好了,被全世界很多大学采用,也成为了很多程序员的必读经典。
这本书的核心思想是:从程序员的视角来理解计算机系统。它不是讲计算机硬件的,也不是讲操作系统的,而是讲程序员需要知道的计算机系统知识。它把计算机系统的各个部分串起来,让你理解一个程序从源代码到运行的整个过程,以及这个过程中计算机系统是如何工作的。
这本书的内容很全面,主要包括以下几个部分:
第一部分,计算机系统的漫游。这部分是全书的概述,从一个简单的hello程序开始,讲述了程序从源代码到可执行文件,再到运行的整个过程。这部分是全书的总纲,读了这部分,你就能对计算机系统有一个整体的认识。
第二部分,程序结构和执行。这部分讲了信息的表示和处理、程序的机器级表示、处理器体系结构、优化程序性能、存储器层次结构。这部分是从硬件和底层的角度,讲程序是如何在计算机上执行的。
第三部分,程序间的交互和通信。这部分讲了链接、异常控制流、虚拟内存、系统级I/O、网络编程、并发编程。这部分是从操作系统和系统编程的角度,讲程序之间是如何交互和通信的。
这本书的内容很多,也很深,但写得很有条理,循序渐进。每一章都有大量的例子和练习题,帮助你理解和巩固知识。
为什么这本书是必读书
很多人问我,计算机基础的书那么多,为什么一定要读CSAPP?
我的答案是:因为这本书能帮你建立计算机系统的整体认知,让你从一个"只会写代码的程序员"变成一个"理解系统的程序员"。
具体来说,这本书有以下几个价值:
第一,建立整体认知。很多程序员对计算机系统的理解是碎片化的。知道CPU,但不知道CPU是怎么执行指令的;知道内存,但不知道内存是怎么管理的;知道操作系统,但不知道操作系统是怎么和硬件交互的。CSAPP把这些碎片化的知识串起来,让你理解计算机系统的整体架构和工作原理。读完这本书,你会对计算机系统有一个整体的、系统的认识,而不再是一知半解。
第二,从程序员的视角。很多计算机系统的书,要么是从硬件工程师的视角讲,要么是从操作系统开发者的视角讲,对于普通程序员来说太底层了,用不上。CSAPP是从程序员的视角讲的,它讲的都是程序员需要知道的计算机系统知识。比如,为什么你的程序会有性能问题?为什么你的程序会内存泄漏?为什么你的程序会出现并发问题?这些问题的答案,都在这本书里。
第三,理论和实践结合。CSAPP不是一本纯理论的书,它有大量的实践内容。每一章都有练习题和实验,让你动手实践。比如,你会写一个反汇编器,写一个缓存模拟器,写一个shell,写一个web服务器。通过这些实践,你能真正理解计算机系统的工作原理,而不只是停留在理论层面。
第四,经典且不过时。这本书虽然已经出了好几版,但核心内容是不过时的。计算机系统的基本原理,比如冯诺依曼架构、存储器层次结构、虚拟内存、进程和线程,这些东西几十年都没有变过,未来也不会有太大的变化。读这本书,你学到的是计算机系统的本质,而不是某个具体的技术。本质的东西是不会过时的。
第五,面试必备。如果你要找技术工作,特别是大厂的技术工作,CSAPP的内容是面试的重点。很多面试题,比如进程和线程的区别、虚拟内存的原理、TCP的三次握手、并发编程的问题,这些内容在CSAPP里都有详细的讲解。读好这本书,面试的时候就能从容应对。
这些价值,是其他很多书比不了的。所以我说,CSAPP是计算机基础领域的必读书。
第一部分:计算机系统的漫游
第一部分是全书的概述,也是我最喜欢的部分。
这部分从一个简单的hello程序开始:
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}就是这么一个简单的程序,作者用它来讲了计算机系统的整个工作流程。
首先,你用编辑器写了这个程序,保存为hello.c。这个文件是一个文本文件,由ASCII字符组成。
然后,你用编译器把它编译成可执行文件。编译的过程分为四个阶段:预处理、编译、汇编、链接。预处理阶段处理#include和#define等预处理指令;编译阶段把C代码翻译成汇编代码;汇编阶段把汇编代码翻译成机器指令;链接阶段把程序需要的库函数链接进来,生成最终的可执行文件。
接下来,你在shell里输入./hello,运行这个程序。shell会解析命令,然后调用操作系统的系统调用,加载hello程序到内存中。CPU开始执行程序的指令,调用printf函数,把"hello, world"输出到屏幕上。
最后,程序执行完毕,退出,shell等待下一个命令。
就是这么一个简单的过程,涉及到了计算机系统的各个部分:文件系统、编译器、汇编器、链接器、操作系统、CPU、内存、I/O设备。作者用这个例子,把计算机系统的整体架构讲清楚了。
读这部分的时候,我最大的感受是:原来一个简单的程序背后,有这么多复杂的过程。以前写程序的时候,从来没有想过这些,只是写完代码编译运行就行了。现在知道了背后的原理,对程序的理解更深了。
这部分虽然是概述,但信息量很大。建议多读几遍,把每个环节都搞清楚。这部分搞懂了,后面的内容就容易理解了。
第二部分:程序结构和执行
第二部分讲程序的结构和执行,这部分是从硬件和底层的角度来讲的。
这部分包括五章:信息的表示和处理、程序的机器级表示、处理器体系结构、优化程序性能、存储器层次结构。
信息的表示和处理这一章,讲了计算机中信息的表示方法,包括整数、浮点数、位运算。这章看起来简单,但实际上有很多细节。比如,整数的补码表示,为什么要有补码?浮点数的IEEE 754标准,为什么浮点数会有精度问题?这些问题,很多程序员都答不上来。读了这章,你就能彻底搞懂。
程序的机器级表示这一章,讲了汇编语言。很多人觉得汇编语言没用,现在都用高级语言了,谁还写汇编?但实际上,理解汇编语言对于理解程序的执行非常重要。这章讲了x86-64的汇编语言,包括数据格式、访问信息、算术和逻辑操作、控制流、过程、数组和结构体、浮点代码。读了这章,你就能看懂汇编代码,理解高级语言是怎么翻译成机器指令的。这对于调试程序、优化性能都很有帮助。
处理器体系结构这一章,讲了CPU的内部结构和工作原理。这章从一个简单的顺序处理器开始,逐步讲了流水线处理器的设计。读了这章,你就能理解CPU是怎么执行指令的,什么是流水线,什么是冒险,什么是分支预测。这些知识,对于理解程序的性能非常重要。
优化程序性能这一章,讲了如何优化程序的性能。这章很实用,讲了很多优化技巧,比如消除循环中的低效代码、减少过程调用、消除不必要的内存引用、循环展开、利用条件传送代替分支。这些技巧,都是从编译器和CPU的角度出发的,理解了底层原理,才能写出高性能的代码。
存储器层次结构这一章,讲了计算机的存储器层次结构。从寄存器、缓存、主存到磁盘,每一层的速度和容量都不一样。这章重点讲了缓存的原理,包括缓存的组织结构、缓存的命中率、缓存的优化。读了这章,你就能理解为什么有些程序跑得快,有些程序跑得慢,为什么数据的访问顺序会影响性能。这些知识,对于写高性能程序非常重要。
这部分是全书的重点,也是最难的部分。特别是处理器体系结构和存储器层次结构,需要花时间去理解。但这部分也是最有价值的,理解了这部分,你对计算机系统的理解就上了一个台阶。
第三部分:程序间的交互和通信
第三部分讲程序间的交互和通信,这部分是从操作系统和系统编程的角度来讲的。
这部分包括六章:链接、异常控制流、虚拟内存、系统级I/O、网络编程、并发编程。
链接这一章,讲了程序的链接过程。包括静态链接、目标文件、可重定位目标文件、符号解析、重定位、可执行目标文件、加载、动态链接、库、位置无关代码。读了这章,你就能理解程序是怎么链接起来的,什么是静态库和动态库,为什么会有链接错误,什么是位置无关代码。这些知识,对于理解程序的构建过程很有帮助。
异常控制流这一章,讲了计算机系统中的异常控制流。包括异常、进程、进程控制、信号、非本地跳转。读了这章,你就能理解什么是异常,什么是中断,什么是进程,进程是怎么创建和终止的,信号是怎么工作的。这些知识,是理解操作系统的基础。
虚拟内存这一章,讲了虚拟内存的原理。这是全书最重要也最难的一章。包括物理和虚拟寻址、地址空间、虚拟内存作为缓存的工具、虚拟内存作为内存管理的工具、虚拟内存作为内存保护的工具、地址翻译、利用缓存、动态内存分配、垃圾回收、常见的内存错误。读了这章,你就能彻底理解虚拟内存的原理,什么是页表,什么是TLB,什么是缺页异常,什么是内存映射,什么是malloc和free。这些知识,对于理解程序的内存管理非常重要。很多内存问题,比如内存泄漏、野指针、段错误,理解了虚拟内存之后就能彻底搞懂。
系统级I/O这一章,讲了Linux的I/O系统。包括Unix I/O、文件、打开和关闭文件、读和写文件、用RIO包健壮地读写、读取文件元数据、共享文件、I/O重定向、标准I/O。读了这章,你就能理解Linux的文件系统和I/O系统,什么是文件描述符,什么是重定向,什么是管道。这些知识,对于系统编程很有帮助。
网络编程这一章,讲了网络编程的基础。包括客户端-服务器模型、网络、全球IP因特网、套接字接口、Web服务器。读了这章,你就能理解网络的基本原理,什么是IP地址,什么是端口,什么是TCP,什么是HTTP,怎么写一个简单的Web服务器。这些知识,对于理解网络编程很有帮助。
并发编程这一章,讲了并发编程的基础。包括并发的概念、基于进程的并发编程、基于I/O多路复用的并发编程、基于线程的并发编程、多线程程序中的共享变量、用信号量同步线程、使用线程提高并行性、并发程序中的常见问题。读了这章,你就能理解并发编程的原理,什么是进程和线程,什么是竞态条件,什么是死锁,怎么用信号量同步线程。这些知识,对于写并发程序非常重要。
这部分内容很多,也很实用。特别是虚拟内存和并发编程,是面试的重点,也是工作中经常用到的知识。建议重点读这两章。
如何读好这本书
CSAPP是一本好书,但也是一本难读的书。很多人买了这本书,读了几章就读不下去了。怎么才能读好这本书呢?
我有几个建议:
第一,有一定的编程基础再读。这本书假设你已经会写C语言程序,对计算机有基本的了解。如果你是零基础,直接读这本书会很吃力。建议先学一下C语言,写一些简单的程序,有了一定的编程基础之后再读这本书。
第二,不要追求一次读完。这本书的内容很多,也很深,一次读完是不可能的。建议分阶段读,先读第一部分和第二部分,有了一定的基础之后再读第三部分。每一章都要慢慢读,不要赶进度。读懂了再往下读,不懂的地方可以先跳过,等后面的内容读了之后再回头看。
第三,动手做实验。这本书有配套的实验(CMU的CSAPP Labs),包括Data Lab、Bomb Lab、Attack Lab、Cache Lab、Shell Lab、Malloc Lab、Proxy Lab。这些实验非常好,能帮你真正理解书中的内容。建议边读边做实验,读完一章做一章的实验。做实验的过程中,你会遇到很多问题,解决这些问题的过程就是深入理解的过程。
第四,结合实际工作读。如果你已经工作了,可以结合工作中的问题来读这本书。比如,你在工作中遇到了性能问题,就去读优化程序性能和存储器层次结构这两章;你遇到了内存问题,就去读虚拟内存这一章;你遇到了并发问题,就去读并发编程这一章。结合实际问题读,你会理解得更深,也更有动力。
第五,多读几遍。这本书我读了三遍,每一遍都有新的收获。第一遍是大学的时候,囫囵吞枣,很多地方不懂;第二遍是工作两年后,有了一些经验,很多地方懂了;第三遍是最近,又有了新的理解。经典的书就是这样,每读一遍都有新的收获。建议至少读两遍,第一遍通读,第二遍精读。
第六,不要怕难。这本书确实难,特别是处理器体系结构和虚拟内存这两章,很多人读了好几遍都不懂。但不要怕难,难的东西才值得学。多读几遍,多做实验,多思考,慢慢就懂了。当你终于搞懂一个难点的时候,那种成就感是无法形容的。
这些建议,是我读这本书的经验总结。希望能帮你更好地读这本书。
这本书的不足
当然,这本书也不是完美的,也有一些不足。
第一,内容更新不够快。这本书的第三版是2015年出的,到现在已经十年了。虽然核心内容不过时,但一些具体的技术,比如x86-64的指令集、Linux的系统调用,已经有了一些变化。如果你想了解最新的技术,可能需要参考其他资料。
第二,部分内容偏难。这本书的有些章节,比如处理器体系结构、虚拟内存,对于初学者来说太难了。如果没有老师指导,自己读可能会很吃力。建议这些章节可以配合网上的课程和视频来读。
第三,实验环境搭建麻烦。这本书的配套实验需要在Linux环境下做,而且需要安装一些工具。对于用Windows的读者来说,搭建实验环境可能会比较麻烦。建议用虚拟机或者WSL来搭建Linux环境。
第四,中文版翻译一般。这本书的中文版翻译质量一般,有些地方翻译得不够准确,读起来有点拗口。如果英语好的话,建议读英文版。英语不好的话,读中文版也可以,遇到不懂的地方可以对照英文版看。
这些不足,不影响这本书的价值。它仍然是计算机基础领域最好的书之一。
写在最后
《深入理解计算机系统》是我读过的最好的计算机书之一。
它不是一本教你怎么写代码的书,而是一本教你理解计算机系统的书。读了这本书,你会对计算机系统有一个整体的、深入的理解,你会知道程序背后的原理,你会成为一个更好的程序员。
很多人说,现在的程序员不需要懂底层,会用框架就行了。但我不这么认为。底层的知识,决定了你能走多远。当你遇到性能问题、内存问题、并发问题的时候,底层知识就是你的武器。没有底层知识,你只能在表面上修修补补;有了底层知识,你才能从根本上解决问题。
而且,底层知识是不过时的。框架会变,语言会变,但计算机系统的基本原理不会变。今天学的知识,十年后仍然有用。这就是底层知识的价值。
如果你是一个程序员,或者想成为一个程序员,我强烈建议你读一下这本书。它可能会很难,可能会花你很多时间,但读完之后,你会发现一切都是值得的。
最后,用一句话来结束这篇文章:"程序员的道路上,CSAPP是一座必须翻越的山。翻过去,你会看到不一样的风景。"
愿你能在这本书中收获知识,收获成长。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录