《深入理解计算机系统CSAPP(第二版)》读书心得与全书推荐

          最近看了CMU的超强计算机导论课程《Computer System:A Programmer's Perspective》(中文译名《深入理解计算机系统》),现在已经出到第二版,全书内容作为计算机导论课程可以说是一本字典级丛书,覆盖计算机软件硬件的几乎所有内容。

       在看这本书之前,我对于计算机的了解大抵是每个内容了解一些,不能说一点不会,当然也称不上熟悉,总感觉计算机的理论体系深刻地不可捉摸,很多知识只是了解地一知半解,但是这本书将所有的计算机分支内容整合起来,顺理成章地平铺直叙,娓娓道来。很重要的一点就是,从这本书的书名上看,这本书的视点是站在一个程序员的角度的,这也为以后搞程序的众多程序员提供了一种全面了解计算机系统的直观机会。从程序员的角度,我们能够更加清楚地了解程序员应该掌握的硬件知识以及应该了解到什么程度,怎样利用硬件知识来提高程序的性能等等。可以说,这是一本非科班出身的计算机爱好者们的入门级字典全书。

       一直担心自己看英文原版书会很吃力,但是CSAPP完全打消了我关于原版书籍的英文理解的疑虑,作者是CMU的大牛,全书的内容由浅入深,语句叙述简单易懂,英文理解毫无压力,反而感觉对英文增添了许多好感。暂且不说英文书的问题,相信大家都不会太过纠结于此,下面总结一下我看这本书之后的感受吧,我按照全书的12章一一介绍。

Chapter 1 计算机系统漫游

      这一章是介绍性的叙述,关于计算机的编译过程、CPU、硬件组成、缓存、存储器层次、进程、虚地址空间、i7处理器结构等等。首先让我们对于整个计算机的核心内容有一个全面简单的认识,接下来就是深入一点研究它们了。

Chapter 2 信息表达和操作

      这一章首先讲解C语言的版本,对应于不同的GCC命令参数。其次信息的表示是二进制,这就有一个大小端的问题(big endian/little endian),关于这个问题,我用“Intel小不点”表示Intel并且小端是符合常规的(低位在前,而常规是高位在前)。其次介绍了布尔代数,关于异或:x^y=(x&~y)|(~x&y)。紧接着是算术移位和逻辑移位的区别。下面就是本章的重点了,关于Unsigned Encoding和Two's Complement Encoding的讨论,我们一直习惯于认为补码就是原码取反加一,但是这里给出了定义,就是最高位为1代表-2^W,而无符号整数最高位为1代表+2^W
关于他们的加减乘除的转换有一系列的公式,介绍得很详细,有一点最重要的是不管如何赋值其二进制是不变的,赋值给Unsigned int就按无符号整数处理,赋值给Signed int就按二进制补码处理,如何解读与其二进制的1、0组合无关。接着是IEEE754浮点数标准、浮点数舍入规则等等的介绍,没有过于深入,有兴趣的读者可以看看组成原理中关于这一部分的介绍。

Chapter 3 程序的机器级表达

      这一章开始让我对汇编语言有了初步的了解,虽然这里没有涵盖汇编语言全部的内容,但是通过作者的由浅入深的讲解我能够分析程序的反汇编代码了,原来对于addl、movl、mull、pushl等等都一窍不通,现在有点感觉了。这一章首先着重讲解了IA32的程序反汇编代码的内容,之后又延伸到最新的x86-64,讲解操作数多种形式、算术操作、逻辑操作、比较与测试指令、SET指令、跳转指令(conditional jump)、条件分支的翻译(if-else、do-while、while、for)、条件转移(conditional move)、switch语句(使用jump table)。接下来就是过程调用时的栈结构,包括调用者帧(返回地址、传递参数)、当前帧(寄存器、本地变量等)的细节,使得读者能够对程序调用过程要做的过程与栈帧结构了解透彻。下面是数组分配与访问的内容及其访问的汇编代码的内容。再者是异构数据结构,讲的是结构体(struct)和共用体(union),这里引出了数据对齐问题(Data Alignment),分别是windows和linux的不同规定。最后是内存访问越界与缓冲区溢出,这里讲解了著名的缓冲区溢出攻击,采用的是访问数组内存越界地方的内容找到返回地址将其替换为病毒或者寄生程序的起始地址,这样就成功地在返回时将程序的控制权交给了病毒或寄生程序,当然这也有解决方法,书中介绍了三种方法。

Chapter 4 处理器架构

      这一章作者是在用一个设计者的角度讲解如何设计一个小型的处理器架构,以他开发的Y86指令集架构为目标,讲解如何一步一步设计出这样的一个小型的但是考虑基本周全的指令集架构,正是这样的独特的讲解角度,使得整个内容生动鲜活。这一章在设计Y86指令集和硬件操作过程中还涉及到使用硬件控制语言(HCL)的知识,同时对组合电路(Combinational circuits)和时序电路(Sequential Circuits)做了区分和详细介绍,尤其是时序电路,分析信号沿到达前后各寄存器(RF、PC)和程序状态(Stat、CC)的变化过程。在指令集的实现中将指令执行过程分为取指(Fetch)、译码(Decode)、执行(Execute)、访存(Memory)、写回(Write back)和程序计数器更新(PC update),详细分析了所有指令的执行过程及其寄存器、内存内容、PC值变化情况,其实现的硬件结构讲解清晰透彻。接下来就是重点内容——指令流水的实现,要给每个阶段前加上相应的暂存单元,存储上一阶段的寄存器、PC、CC、Stat、icode、ifun等内容,同时要避免数据冒险,可以采用推迟周期(Stalling)、转发(Forwarding)来避免。着重提到了载入/使用冒险(Load/Use Hazard)及其解决方法。之后就是异常处理,对于地址访问异常、指令异常等的处理需要注意的地方。指令流水的实现也同样给出了硬件的结构,包括指令执行的各个阶段。

Chapter 5 提升程序性能

      程序性能的提升如何做到大幅度成倍提升在这里作者一步一步地实现,我们平常编程时习以为常的语句很可能就是导致程序性能不高的原因,比如在循环中重复计算相同的值,只需将它提到循环外就可以减少n-1次该语句的执行,另外循环展开也是提高程序运行性能的重要方法,作者要告诉我们的是我们不仅能从传统意义上的针对编程语言的优化中提升性能,更深入的是我们可以挖掘不同处理器的性能进行优化以提高性能,在讲解中我们发现影响性能提高的最终瓶颈就是执行循环中的指令流水的关键路径,只要不在关键路径上都是可以并行执行的。在这里,作者真的是让我大开眼界,原来程序优化可以这样来。

Chapter 6 存储器层次

      存储器是有层次的,这在计算机组成原理或者计算机导论等课程中都会涉及到,但是作者将这些知识讲解得生动有趣,先从随机存储器讲起,介绍DRAM、SRAM与非易失性存储器,接着是磁盘存储器,介绍其几何结构、磁盘操作及其时间。下面又是本章的重点,也是存储器最重要的一个概念Locality——局部性原理,分为空间局部性和时间局部性,正是它们才使得存储器层次结构成为可能。基于这个核心概念,作者重点介绍了缓存,其三种地址映射方式——直接映射、全相联和组相联的查找更是缓存的核心。

Chapter 7 链接

      如果你对链接的过程不了解的话,这一章绝对是你学习的经典内容,这里介绍了静态链接和动态链接。目标文件.o的格式及其代表的含义在这里都讲的非常详细,重定位的内容,位置无关代码的调用过程等等也很详细。

Chapter 8 异常控制流

      这一章详细介绍了unix的异常控制机制,并且讲到了进程(process)的概念,并讲解了unix中信号(signal)的概念,最后是非本地跳转(nonlocal jump),看完之后对操作系统对异常的控制处理机制,进程之间通信的方式,可移植程序的修改等内容有了清晰的概念。特别是信号的概念,进程如何通信、遇到不同信号如何处理,分析信号通信时需要打破传统意义上的顺序执行程序的概念,因为进程引入了并行的概念,父子进程还可能形成赛跑(race),这也是一个程序可能出错的地方。

Chapter 9 虚拟内存

      这一种可以说是重点了,有了进程之后对内存的访问成了问题,虚拟内存解决了这个问题,使得每个进程都能够有自己的私有虚拟内存,访存时只需进行地址翻译,转换为对应的物理内存就好了。内存是分页的,页表也分层次,只有一级页表常驻内存,其他都需要使用时调入,虚拟内存的大小不是没有限制的,限制它的因素是换入换出区域的大小。为了更快的翻译引入块表,增加了快变的地址翻译过程书中利用一个例子非常透彻的讲解了,感觉受益匪浅。书中介绍了windows和UNIX的虚拟内存实现方法,特别是UNIX需要涉及到内存映射(Memory Mapping),就此还介绍了动态存储分配的内容,分为四种情况。最后简单介绍了编程中可能会遇到的内存相关的bug。

Chapter 10 系统级输入输出

      这一种内容比较少,主要是关于文件打开、关闭、读写与文件共享和输入输出重定向等内容,尤其是读写,这一章为了后面两章的编程做了铺垫,用RIO Package来代替操作系统提供IO读写函数,使得读写更加安全,特别是对于后面讲到的网络服务器程序,读写一定要保证不能出现截断的现象,一旦出现RIO Package就可以实现重复读写直到成功为止。

Chapter 11 网络编程

      这一章介绍网络的客户端服务器架构及其机制、网络IP、域名,尤其是网络套接字接口(Socket Interface),这是客户端与服务器通信的接口。作者在最后实现了一个小型的web 服务器并详细讲解了源代码。

Chapter 12 并发编程

       这一章介绍了并发编程的概念, 讲了三种并发编程的方法: Processes, I/O multiplexing, Threads,最主要的是讲线程(Thread)编程。这里也讲解了信号量,如何利用信号量来进行进程通信。通过经典的生产者-消费者问题、读者-写者问题讲解了怎样处理线程编程中的共享资源。最后讲解了线程安全性、线程赛跑、可重入程序和死锁的概念,特别是在讲解死锁时使用了进程图(process graph)使得死锁一目了然。并发编程也是现在比较流行的一个领域,我看这一章很快,对于线程并发执行的代码也只是初步了解,离能够自己编还差十万八千里,如果想进一步学习的话并发编程是一定得好好学的。

      第一篇博文写了这么多,也花了不少功夫,以后继续努力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值