书名:深入理解计算机系统(原书第2版)
作者:(美)Randal E.Bryant / David O'Hallaron
译者:龚奕利 / 雷迎春
定价:99.00元
豆瓣网:
http://book.douban.com/subject/5333562/
优惠购买链接:http://www.china-pub.com/STATIC/zt_mb/huodong/jsj_shenru_101027/jsj_shenru_101027.asp
内容简介 & 作者简介
内容简介:
作者简介:
Randal E.
Bryant
1973年获得密歇根大学学士学位,随即就读麻省理工学院的研究生院,并在1981年获得计算机博士学位。从1984年至今一直任教于卡内基-梅隆大学,
现在是卡内基-梅隆大学计算机学院院长、教授,同时受邀任教于电子与计算机工程学院。他还是ACM院士、IEEE院士和美国国家工程院院士。其研究成果获
得过数项大奖,其中包括Semiconductor
Research
Corporation颁发的两个发明荣誉奖和一个技术成就奖,ACM颁发的Kanellakis理论与实践奖,还有IEEE授予的W. R. G.
Baker奖、Emmanuel Piore奖和Phil Kaufman奖。
David R. O'Hallaron
现为Intel匹兹堡实验室主任,卡内基-梅隆大学电子和计算机工程学院副教授,并在维吉尼亚大学(University of
Virginia)获得计算机科学的博士学位。他曾获得卡内基-梅隆大学计算机学院颁发的Herbert
Simon杰出教学奖,并同Quake项目中其他成员一起获得了高性能计算领域中的最高国际奖项——Gordon Bell奖。
读者评论收集
本科学过了很多门课程,但是总是感觉每门课本里面讲的都是单独的东西,就我们这样的普通学生来说很难融会贯通,到最后无非就是应试了。但本书站在程序员的 角度,从我们熟悉的代码开始讲,将编译,运行以及在此过程中硬件的处理过程,让人很容易接受...另外,本书相比算法导论来说,还是比较薄的,呵呵,不过 纸张还可以了..
————————————————————————————————————————————————
开始的时候在www.china-pub.com上 看见过这本书,开始我以为和以前看的操作系统类的书差不多,所以没有过多的关注,光C/C++板块的时候,看见介绍,很多人推荐就下载了样章看了下,读第 一章的时候发现和以前看的不一样,这样....不断的看下去,发现自己在一些知识方面理解的不够,很多止于表面(我是个大菜鸟),有很多地方感觉不错。吸 引着我往下面看……
————————————————————————————————————————————————
起点低,覆盖面广,适合大三,大四的本科生;一个优秀程序员必须理解底层操作,对体系结构、操作系统必须有认识,这本书的内容很适合作为起点。
————————————————————————————————————————————————
如果你是个在校生,如果你学完了组成原理和体系结构,强烈建议你看看这本书。
————————————————————————————————————————————————
这本书的确是好书,我没有理由不为此书而拍案叫绝 ,如果学计算机的能够依此书为教材那就再好不过了。看过此书你会对计算机原理、汇编语言和C语言有根本性的认识。
————————————————————————————————————————————————
这本书写得太棒了! 我在很多地方都弄不清楚的概念在此书中都有准确明了的阐述。每个概念都很简洁却都抓住重点。
————————————————————————————————————————————————
经典中的经典。写代码的都应该买一本。
————————————————————————————————————————————————
特别好的一本书,特别是对在校大学生。整个知识体系非常完善,相关阐述也是由浅入深,精品!
————————————————————————————————————————————————
我今天就看到同学在看第一本来着,图书馆借的。“一本书都让人翻得很破了,但还是很难借到。”我同学如是描述这本书怎么火。
————————————————————————————————————————————————
读完两章电子版,觉得此书是非要不可了!
第一章,讲程序是如何在计算机上运行,通过图文进行讲解,让读者更加容易对程序的执行过程有一个全局的了解,为后续的章节知识做铺垫(估计),对于那些对程序是如何在底层运行不是很清晰的程序员,此章很有用!
第
二章,讲信息的表示和处理,其实说白了就是讲解二进制和十六进制的一些运算,其中穿插有一些练习题和一些程序的小技巧,例如:不用临时变量进行整数的交
换。此章有一些推导公式,显得比较冗长沉闷,但是章节开头就教你怎样阅读此章,先是跳过推导过程,做给出的练习题,后面再回来看推导过程。
此书的阅读起点不高,只要有一些C语言背景知识就可以阅读了,对于计算机专业的课程更是一个完整的总结!
强烈推荐购买!
————————————————————————————————————————————————
现在正在读,计算机专业的强烈建议读一读
现在想想大学的时候,纠结于MFC、JAVA、C++等技术,可是却忘了基础是最重要的,要是能着两年知道这本书就好了
豆瓣上这本书打分9.5,可见大家对这本书的认可
http://book.douban.com/subject/1230413/
————————————————————————————————————————————————
如
果大学只能带走一本书的话,我选择这本。
这是本很有趣的书,了解计算机底层技术是件极富挑战同趣味的事情。大二以后基本没再阅读过哲学历史文学方面的书籍,因为这样的书籍足以给人带来极大乐趣。
个人认为这样的书籍,计科专业的本科学生越早接触越好,它会让你比别人更早拥有一个系统的计算机知识,更能触类旁通。如果想从事底层开发或在Linux平
台下开发,这本书是很好的选择。
另外,这本书的翻译纸张都很不错,很多的词汇译者都在前面做了说明。这是为数不多让人不抱怨翻译的技术书籍,如果英文不过硬,看中文版也是很享受的一件事
情。 聪明的你会喜欢这本书的。
————————————————————————————————————————————————
这本书的第一章计算机系统漫游挺好,看上去就跟看小说似的,引人入胜,不知不觉就先了解了好多东西。
这本书是早看早好,一接触计算机技术就能看了,对以后理解问题很有帮助,难得的好书呀
看了迷你书上写的,“起点低”,时候大三大四的本科生,其实还可以更低,懂C语言了解点汇编了解点操作系统就可以看了,看书的过程中这些还会慢慢深入学习。该书对许多概念讲的都挺清楚,深度合适。
习题放置的位置也很不错,适当的段落后就有少量小习题提供给读者检测自己是否理解,基本都有答案的。整章后面还有更多问题供读者思考。
————————————————————————————————————————————————
看过第一版,很有深度,不能全都掌握。打算重新啃一遍。
————————————————————————————————————————————————
作为一个程序员,学习了计算机系统,也学习了计算机组成原理,总感觉还是少了什么,没有把软件和硬件很好的串联起来,这本书恰好解决了这个问题,站在程序员的角度,对计算机系统进行了深刻的阐述,让我受益匪浅,真的是一本不可多得的好书!
————————————————————————————————————————————————
书还不错,可惜快递把侧面胶搞碎了,遗憾。
粗略地浏览了一下,本书的覆盖面确实很广,底层的介绍通俗易懂;从第一版的反映来看,内容确实没什么好
说的。剩下的就是好好研读每一章节了。从1、2章的翻译来看,还可以,算是很不错了,不过还没有达到有些人描述得那样,翻译得“很好”,只能说翻译得还不
错,起码不会让你读起来感觉有些奇怪。期待原汁原味的影印版。
总之,本书的价值远远大于它的价格。
CSAPP译者序
《深入理解计算机系统》是通过程序员的视角来介绍计算机系统,首先把高级语言转换成计算机所能理解的一种中间格式(如汇编语言),然后描述计算机如何解释和执行这些中间格式的程序,是系统的哪一部分影响程序的执行效率。在讲述计算机系统知识的同时,也给出了关于C语言和汇编语言的编程、阅读技巧以及基本的系统编程工具,还给出一些方法帮助程序员基于对计算机系统的理解来改善程序的性能等问题。本书强调对计算机系统概念的理解,但并不意味着不动手。如果按照本书的安排做每一章后面的习题,将有助于理解和加深正文所述的概念和知识,更可以从实际动手中学习到新的知识。
本书的主要内容是关于计算机体系结构与编译器和操作系统的交互,包括:数据表示;汇编语言和汇编级计算机体系结构;处理器设计;程序的性能度量和优化;程序的加载器、链接器和编译器;包括I/O和设备的存储器层次结构;虚拟存储器;外部存贮管理;中断、信号和进程控制。
本书的最大优点是为程序员描述计算机系统的实现细节,帮助其在大脑中构造一个层次型的计算机系统,从最底层的数据在内存中的表示(如大多数程序员一直陌生或疑惑的浮点数表示),到流水线指令的构成,到虚拟存储器,到编译系统,到动态加载库,到最后的用户态应用。贯串本书的一条主线是使程序员在设计程序时,能充分意识到计算机系统的重要性,建立起被所写程序可能被执行的数据或指令流图,明白当程序被执行时,到底发生了什么事。从而能设计出一个高效、可移植、健壮的程序,并能够更快地对程序排错、改进程序性能等。
原书是卡耐基-梅隆大学(CMU)的教材,现在很多国内外著名的大学也选用其为教材或辅助性资料,因此,本书的读者不仅仅是那些因为工作和兴趣而关注本书的人,还包括一些在校的大学生。我们认为,在校学生越早接触本书的内容,将越有利于他们学习计算机的相关课程,培养对计算机系统的研究兴趣。
总的来说,《深入理解计算机系统》一书是一个桥梁,它帮助程序员衔接了计算机系统的各个领域的知识,为程序员构造了一个概念性框架。对于各个领域,如计算机系统结构、操作系统、编译器、网络、并发编程的知识进一步获取,还需要进一步阅读相关书籍。
《深入理解计算机系统》从第一版到第二版,已经是七年的时光了。由于计算机技术的飞速发展,第二版相对于第一版做了大量的修改。首先,针对硬件技术和编译器技术的变化,第二版对系统的介绍,特别是实际使用部分,做了增加和修改。例如,既保持了原有的针对32位系统的说明,又增加了对64位系统的描述。其次,第二版增加了很多关于由算术运算溢出以及缓冲区溢出造成安全漏洞的内容。第三,更详细讲述了处理器对异常的发现和处理,这是计算机系统中的一个重点和难点。第四,对存储器的描述改为了基于Intel Core i7处理器的存储器层次结构,还增加了固态硬盘的内容。第五,强调了并发性,并发性既体现在处理器的实现中,也体现在应用程序编程中。
这次我们不仅对第二版较第一版有改动之处做了仔细的翻译,而且对第一版之译稿做了重新审视,重新校正,精益求精。比如,在保证原意正确的情况下,对一些句式做了变动,还有尽量减少被动语态的使用等,以符合中文的习惯。再如,根据我这几年教授《计算机体系结构》课程的经验,改变了某些术语的翻译,使之更接近于中文教科书中的术语使用。
本书中有些术语的翻译还是让我们难以抉择。在此,我们预先做一些解释和说明。Operator这个词,如果根据上下文,它表示的是一个运算,我们就翻译成运算符。如果它对应于一个操作,我们就翻译成操作符。Local variable,可以翻译成局部变量,也可以翻译成本地变量。考虑到还有local data、local buffer等词,我们选择统一将local翻译成“局部的”。Chunk这个词是一片或者一块的意思,常常用来表示一块连续的内存区域。它在第6、7和9章中出现较多。为了使之区别于block(块),我们选择将其翻译成“片”。
本书内容多,篇幅长,出于降低印刷成本和最后定价的考虑,我们不得不忍痛割爱,在中文版中不附上附录。经常读计算机书籍的读者都知道附录对于一本书完整度的重要性,所以,我们还是对附录进行了翻译和编辑,放到华章图书的网站以及一些相关网站上,供大家参考使用。
刘晓文、李晓玲、邱文卓和张育也参与了翻译和校对工作。在此,还要感谢王文杰,经常和我们一起讨论翻译中遇到的问题。还要感谢本书的编辑王春华,您的耐心和认真让我们非常感动。
由于本书内容量大,翻译时间紧迫,尽管我们尽量做到认真仔细,但还是难以避免出现错误和不尽如人意的地方。在此欢迎广大读者批评指正,我们也会把勘误表及时在网上更新,便于大家阅读。
龚奕利,雷迎春
2010年9月于珞珈山
CSAPP前言
《深入理解计算机系统》(Computer Systems: A Programmer’s Perspective,CS: APP)这本书的主要读者是计算机科学家、计算机工程师,以及那些想通过学习计算机系统的内在运作而能够写出更好程序的人。
我们的目的是解释所有计算机系统的本质概念,并向你展示这些概念是如何实实在在地影响应用程序的正确性、性能和实用性的。其他的系统书都是从建造者的角度来写的,讲述如何实现硬件或是系统软件,包括操作系统、编译器和网络接口。而本书是从程序员的角度来写的,讲述应用程序员如何能够利用系统知识来写出更好的程序。当然,学习一个计算机系统应该做些什么是学习如何构建一个计算机系统的很好的出发点,所以,对于希望继续学习系统软硬件实现的人来说,本书也是一本很有价值的介绍性读物。
如果你研究和领会了这本书里的概念,你将开始你的成为极少数的“牛人”之路,这些“牛人”知道事情是如何运作的,也知道当事情出现故障时如何修复他。我们的目标是以一种你会立刻发现很有用的方式来呈现这些基本概念。同时,你也要做好更深入探究的准备,研究像编译器、计算机体系结构、操作系统、嵌入式系统和网络互联这样的题目。
读者所应具备的背景知识
本书中的机器代码表示是基于英特尔及其竞争者支持的两种相关联的格式,俗称 “x86”。对于很多系统来说,IA32机器代码已经成为一种事实上的标准。x86-64是IA32的一种扩展,它允许程序操作更多的数据,引用更广范围的内存地址。由于x86-64系统可以运行IA32的代码,因而在可预见的未来,这两种格式的机器代码都会得到广泛的应用。我们考虑的是这些机器如何在Unix或类Unix(比如Linux)操作系统上运行C语言程序。(为了简化表述,我们用术语Unix来统称所有继承自Unix的系统,包括Solaris、MacOS和Linux在内。)文中包含有大量已在Linux系统上编译和运行过的程序范例。我们假设你能访问一台这样的机器,并且能够登录,能够做一些诸如切换目录之类的简单操作。
如果你的计算机运行的是Microsoft Windows系统,你有两种选择。第一种选择是,获取一个Linux的拷贝(参见www.ubuntu.com),然后安装Linux作为“双重启动”的一个选项,这样你的机器就能运行其中任意一个操作系统了。另一种选择就是,通过安装Cygwin工具(www.cygwin.com),你就能在Windows下得到一个类似Unix的外壳(shell)以及一个非常类似于Linux所提供的环境。不过,Cygwin并不能提供所有的Linux功能。
我们还假设你对C和C++有一定的了解。如果你以前只有Java经验,那么你需要付出更多的努力来完成这种转换,不过我们也会帮助你。Java和C有相似的语法和控制语句。不过,有一些C 语言的内容,特别是指针、显式的动态内存分配和格式化I/O,Java中都是没有的。所幸的是,C是一个较小的语言,在Brain Kernighan和Dennis Ritchie经典的“K&R”文字中得到了清晰优美的描述[58]。无论你的编程背景如何,都应该考虑将K&R作为你个人系统书籍收藏的一部分。
这本书的前几章揭示了C语言程序和它们相对应的机器语言程序之间的交互作用。机器语言示例都是用运行在IA32和x86-64处理器上的GNU GCC编译器生成的。我们不需要你以前有任何硬件、机器语言或是汇编语言编程的经验。
C语言初学者?关于C编程语言的建议
为了帮助C语言编程背景薄弱(或全无背景)的读者,我们在书中加入了这样一些专门的注释来突出C中一些特别重要的特性。我们假设你熟悉C++或Java。
如何阅读此书
从程序员的角度来学习计算机系统是如何工作的会非常有趣,主要是因为你可以主动地来做这件事情。无论何时你学到一些新的东西,都可以马上试验并且直接看到运行结果。事实上,我们相信学习系统的惟一方法就是做(do)系统,即在真正的系统上解决具体的问题,或是编写和运行程序。
这个主题观念贯穿全书。当引入一个新概念时,将会有一个或多个练习题紧随其后,你应该马上做一做来检验你的理解。这些练习题的解答在每章的末尾。当你阅读时,尝试自己来解答每个问题,然后再查阅答案,看看自己是否正确。每一章后面都有一组难度不同的家庭作业题。你的指导老师在教师手册中有这些问题的答案。对每个家庭作业题,我们标注了我们认为的难度级别:
◆只需要几分钟。几乎或完全不需要编程。
◆◆可能需要将近20分钟。通常包括编写和测试一些代码,许多都源自我们在考试中出的题目。
◆◆◆需要很大的努力,也许是1~2个小时。一般包括编写和测试大量的代码。
◆◆◆◆一个实验作业,需要将近10个小时。
文中每段代码示例都是经过GCC编译并在Linux系统上测试后直接生成的,没有任何人为的改动。当然,你的系统上GCC的版本可能不同,或者根本就是另外一种编译器,那么你的编译器可能生成不一样的机器代码,但是整体行为表现应该是一样的。所有的源程序代码都可以从CS:APP的主页(csapp.cs.cmu.edu)上获取。在本文中,源程序的文件名列在两条水平线的右边,水平线之间是格式化的代码。比如,图1中的程序能在code/intro目录下的hello.c文件中找到。我们鼓励你,当遇到这些示例程序时,在你的系统上试试运行它们。
————————————————————————————————————————
——————————————————————————————————————————
图1 一个典型的代码示例
为了避免使本书体积过大,内容过多,我们创建了许多网络旁注(Web asides),包括一些对本书主要内容的补充资料。本书中用CHAP:TOP这样形式的标记来引用这些旁注,这里CHAP是该章主题的一个缩写编码,而TOP是涉及的话题的缩写代码。例如,网络旁注DATA:BOOL包含有对第二章中数据表示里面有关布尔代数的内容的补充资料;而网络旁注ARCH:VLOG包含的是用Verilog硬件描述语言来做处理器设计的资料,是对第四章中处理器设计部分的补充。所有的网络旁注都可以从CS:APP的主页上获取。
旁注:什么是旁注?
整本书中,你将会遇到很多以这种形式出现的旁注。旁注是附加说明,能使你对当前讨论的主题多一些了解。旁注可以有很多用处。一些是小的历史故事。例如,C语言、Linux和Internet是从何而来的?有些地方,旁注是用来澄清学生们经常感到疑惑的问题。例如,高速缓存的行、组和块有什么区别?还有的地方,旁注给出了一些现实世界的例子。例如,一个浮点错误怎么毁掉了法国的一枚火箭,或是一个真正的希捷磁盘驱动器看上去是什么样子的。最后,还有一些旁注仅仅就是一些有趣的东东,例如,什么是“hoinky”?
本书概述
CS:APP这本书由12章组成,旨在阐述计算机系统的核心概念。
· 第1章:计算机系统漫游。这一章通过研究“hello, world”这个简单程序的生命周期,介绍计算机系统的主要概念和主题。
· 第2章:信息的表示和处理。我们讲述了计算机的算术运算,重点描述了会对程序员有影响的无符号数和数的二进制补码(two’s complement)表示的特性。我们考虑数字是如何表示的,以及由此确定对于一个给定的字长,其可能编码值的范围。我们讨论该如何表示数字,以及因此用给定的字长能编码的数值的范围。我们探讨有符号和无符号数字之间类型转换的效果,还阐述算术运算的数学特性。菜鸟级程序员经常很惊奇地了解到(用二进制补码表示的)两个正数的和或者积可能为负。另一方面,二进制补码的算术运算满足代数环的特性,因此,编译器可以很安全地把一个常量乘法转化为一系列的移位和加法。我们用C语言的位级操作来说明布尔代数的原理和应用。我们从两个方面讲述了IEEE标准的浮点格式:一是如何用它来表示数值,一是浮点运算的数学属性。
对计算机的算术运算有深刻的理解是写出可靠程序的关键。比如,程序员和编译器不能用表达式(x-y<0)来替代(x<y),因为前者可能会产生溢出。甚至于也不能用表达式(-y<-x)来替代,因为在二进制补码表示中负数和正数的范围是不对称的。算术溢出是造成程序错误和安全漏洞的一个常见根源,然而很少有书从一个程序员的角度来讲述计算机算术运算的特性。
· 第3章:程序的机器级表示。我们教读者如何阅读由C编译器生成的IA32和x86-64汇编语言。我们说明为不同控制结构,比如条件、循环和开关语句,生成的基本指令模式。我们还讲述过程的执行,包括栈分配、寄存器使用惯例和参数传递。我们讨论不同数据结构如结构、联合(union)和数组的分配和访问方式。我们还以分析程序在机器级的样子作为途径,来理解常见的代码安全漏洞,例如,缓冲区溢出,以及理解程序员、编译器和操作系统可以采取的减轻这些威胁的措施。学习本章的概念能够帮助读者成为更好的程序员,因为你们懂得你们的程序在机器上是如何表示的。另外一个好处就在于读者会对指针有非常全面而具体的理解。
· 第4章:处理器体系结构。这一章讲述基本的组合和时序逻辑元素,并展示这些元素如何在数据通路(datapath)中组合到一起,来执行IA32指令集的一个称为“Y86”的简化子集。我们从设计单时钟周期、非流水线化的数据通路开始,这个设计概念上非常简单,但是运行速度不会太快。然后我们引入流水线化(pipelining)的思想,将处理一条指令所需要的不同步骤实现为独立的阶段。这个设计中,在任何时刻,每个阶段都可以处理不同的指令。我们的五阶段处理器流水线更加实用了。本章中处理器设计的控制逻辑是用一种称为HCL的简单硬件描述语言来描述的。用HCL写的硬件设计能够编译和链接到本书提供的模拟器中,还可以根据这些设计生成Verilog描述,它适合合成(synthesis)到实际可以运行的硬件上去。
· 第5章:优化程序性能。在这一章里,我们介绍了许多提高代码性能的技术,主要思想就是程序员通过让编译器能够生成更有效的机器代码来学习编写C代码。我们一开始介绍的是减少程序需要做的工作的变换,这些是在任何机器上写任何程序时都应该遵循的。然后讲的是增加生成的机器代码中指令级并行度的变换,因而提高了程序在现代“超标量(superscalar)”处理器上的性能。为了解释这些变换行之有效的原理,我们介绍了一个简单的操作模型,它描述了现代乱序(out-of-order)处理器是如何工作的,然后给出了如何根据一个程序的图形化表示中的关键路径来测量一个程序可能的性能。你会惊讶于对C代码做一些简单的变换能给程序带来多大的速度提升。
· 第6章:存储器层次结构。对应用程序员来说,存储器系统是计算机系统中最直接可见的部分之一。到目前为止,读者一直认同这样一个存储器系统概念模型,认为它是一个有一致访问时间的线性数组。实际上,存储器系统是一个由不同容量、造价和访问时间的存储设备组成的层次结构。我们讲述不同类型的随机存取存储器(RAM)和只读存储器(ROM),以及磁盘和固态硬盘(译者注:直译应为固态驱动器,但固态硬盘一词已经被大家接受,所以延用)的几何形状和组织构造。我们描述这些存储设备是如何放置在层次结构中的,讲述访问局部性是如何使这种层次结构成为可能的。我们通过一个独特的观点使这些理论具体化、形象化,那就是将存储器系统视为一个“存储器山”,山脊是时间局部性,而斜坡是空间局部性。最后,我们向读者阐述如何通过改善程序的时间局部性和空间局部性来提高应用程序的性能。
· 第7章:链接。本章讲述静态和动态链接,包括的概念有可重定位的(relocatable)和可执行的目标文件、符号解析、重定位(relocation)、静态库、共享目标库,以及与位置无关的代码。大多数讲述系统的书中都不讲链接,出于下面几个原因,我们要讲述它。第一,程序员遇到的最令人迷惑的问题中,有一些是和链接时的小故障有关的,尤其是对那些大型软件包来说。第二,链接器生成的目标文件是与一些像加载、虚拟存储器和存储器映射这样的概念相关的。
· 第8章:异常控制流。在本书的这个部分,我们通过介绍异常控制流(比如,除了正常分支和过程调用以外的控制流的变化)的一般概念打破单一程序的模型。我们给出存在于系统所有层次的异常控制流的例子,从底层的硬件异常和中断,到并发进程的上下文切换,到由于Unix信号传送引起的控制流突变,到C语言中破坏栈原则的非本地跳转(nonlocal jump)。
在这一章,我们介绍进程的基本概念,进程是对一个正在执行的程序的一种抽象。读者会学习到进程是如何工作的,以及如何在应用程序中创建和操纵进程。我们会展示应用程序员如何通过Unix系统调用来使用多个进程。学完本章之后,读者就能够编写带作业控制的Unix外壳(shell)了。同时,这里也会向读者初步展示程序的并发执行会引起不确定的行为和后果。
· 第9章:虚拟存储器。我们讲述虚拟存储器系统是希望读者对它是如何工作的以及它的特性有所了解。我们想让读者了解为什么不同的并发进程各自都有一个完全相同的地址范围,能共享某些页,而又独占另外一些页。我们还覆盖讲了一些管理和操纵虚拟存储器的问题。特别地,我们讨论了存储分配操作,就像Unix的malloc和free操作。阐述这些内容是出于下面几个目的。它加强了这样一个概念,那就是虚拟存储器空间只是一个字节数组,程序可以把它划分成不同的存储单元。它帮助读者理解包含有像存储泄漏和非法指针引用这样存储器引用错误的程序的后果。最后,许多应用程序员编写自己的优化了的存储分配操作来满足应用程序的需要和特性。这一章比其他任何一章都更能展现将计算机系统中的硬件和软件结合起来阐述的优点。而传统的计算机体系结构和操作系统书都只讲述了虚拟存储器的某一方面。
· 第10章:系统级I/O。我们讲述Unix I/O的基本概念,例如文件和描述符。我们描述如何共享文件,I/O重定向是如何工作的,还有如何访问文件的元数据。我们还开发了一个健壮的带缓冲区的I/O包,可以正确处理一种称为short counts的奇特行为,也就是库函数只读取一部分的输入数据。我们阐述C的标准I/O库,以及它与Unix I/O的关系,重点谈到标准I/O的局限性,这些局限性使之不适合网络编程。总地说来,本章的论题是后面两章网络和并发编程的基础。
· 第11章:网络编程。对编程而言,网络是非常有趣的I/O设备,将许多我们前面文中学习的概念,比如进程、信号、字节顺序(byte ordering)、存储器映射和动态存储器分配,联系在一起。网络程序还为下一章的主题——并发,提供了一个很令人信服的上下文。本章只是网络编程的一个很小的部分,使读者能够编写一个Web服务器。我们还讲述位于所有网络程序底层的客户端-服务器模型。我们展现了一个程序员对Internet的观点,并且教读者如何用套接字(socket)接口来编写Internet客户端和服务器。最后,我们介绍超文本传输协议HTTP,并开发了一个简单的迭代式(iterative)Web服务器。
· 第12章:并发编程。这一章以Internet服务器设计为例介绍了并发编程。我们比较对照了三种编写并发程序的基本机制(进程、I/O多路复用技术和线程),并且展示如何用它们来建造并发Internet服务器。我们探讨了用P、V信号操作来实现同步、线程安全和可重入(reentrancy)、竞争条件以及死锁等的基本原则。对大多数服务器应用来说,写并发代码都是很关键的。我们还讲述了线程级编程的使用方法,来解释应用程序中的并行性,使得程序在多核的处理器上能执行得更快。使所有的核来解决同一个计算问题需要很小心谨慎的协调并发的线程,既要保证正确性,又要争取获得高性能。
本版新增内容
本书的第一版于2003年出版。考虑到计算机技术发展如此迅速,这本书的内容还算是保持得令人吃惊的好。事实证明Intel x86的机器上运行类Unix操作系统,加上采用C语言编程是一种能够涵盖当今许多系统的组合。硬件技术和编译器的变化,以及很多老师教授这些内容的经验,都促使我们做了大量的修改。
下面列出的是一些更加详细的改进:
l 第2章:信息的表示和处理。通过更加详细地解释概念以及更多的练习和家庭作业,我们试图使这部分内容更加易懂。我们将一些比较偏理论的内容放到了网络旁注里。还讲述了一些由于计算机算术运算的溢出造成的安全漏洞。
l 第3章:程序的机器级表示。我们将内容的覆盖范围扩展到了包括x86-64,也就是将x86处理器扩展到了64位字长。也使用了更新版本的gcc产生的代码。另外还增强了对缓冲区溢出漏洞的描述。在网络旁注里,我们给出了两类不同的浮点指令,还介绍了当编译器试图做更高等级优化的时候,做的一些奇特的变换。另外,还有一个网络旁注描述了如何在一个C语言程序中嵌入x86汇编代码。
l 第4章:处理器体系结构。更加详细地说明了我们的处理器设计中的异常发现和处理。在网络旁注里,我们也给出了我们的处理器设计的Verilog描述映射,使得我们的设计能够综合到可运行的硬件上。
l 第5章:优化程序性能。我们极大地改变了对乱序处理器如何运行的描述,还提出了一种简单的技术,能够基于程序的数据流图表示中的路径来分析程序的性能。在网络旁注里,描述了C语言程序员如何能够利用较新的x86处理器中提供的SIMD(单指令流,多数据流)指令来编程。
l 第6章:存储器层次结构。我们增加了固态硬盘的内容,还更新了我们的表述,使之基于Intel Core i7处理器的存储器层次结构。
l 第7章:链接。本章的变化不大。
l 第8章:异常控制流。我们改进了对于进程模型如何引入一些基本的并发概念的讨论,例如,非确定性。
l 第9章:虚拟存储器。我们更新了我们的存储器系统案例研究,采用了64位Intel Core i7处理器为例来讲述。我们还更新了malloc函数的示例实现, 使之既能在32位也能在64位环境中执行.
l 第10章:系统级I/O。本章的变化不大。
l 第11章:网络编程。本章变换不大。
l 第12章:并发编程。我们增加了关于并发性一般原则的内容,还讲述了程序员如何利用线程级并行性使得程序在多核机器上能运行得更快。
此外,我们还增加和修改了很多练习和家庭作业题目。
本书的起源
本书起源于1998年秋季我们在卡内基梅隆(CMU)大学开设的一门编号为15-213的介绍性课程:计算机系统导论(Introduction to Computer System,ICS)[14]。从那以后,每学期都开设了ICS这门课程,每期有150-250名学生,从本科二年级到硕士研究生都有,所学专业也很广泛。这门课程是卡内基梅隆大学计算机科学系(CS)以及电子和计算机工程系(ECE)所有本科生的必修课,也是大多数高级系统课程的先行必修课。
ICS这门课程的宗旨是用一种不同的方式向学生介绍计算机。因为,我们的学生中几乎没有人有机会亲自去构造一个计算机系统。另一方面,大多数学生,甚至包括所有的计算机科学家和计算机工程师,也需要日常使用计算机和编写计算机程序。所以我们决定从程序员的角度来讲解系统,并采用这样的原则来过滤要讲述的内容:我们只讨论那些影响用户级C语言程序的性能、正确性或实用性的主题。
比如,我们排除了诸如硬件加法器和总线设计这样的主题。虽然我们谈及了机器语言,但是重点并不在于如何手工编写汇编语言,而是关注C语言编译器是如何将C语言的结构翻译成机器代码的,包括编译器是如何翻译指针、循环、过程调用以及开关(switch)语句的。更进一步地,我们将更广泛和全盘地看待系统,包括硬件和系统软件,涵盖了包括链接、加载、进程、信号、性能优化、虚拟存储器、I/O以及网络与并发编程等在内的主题。
这种做法使得我们讲授ICS课程的方式对学生来讲既实用、具体,还能动手,同时也非常能调动学生的积极性。很快地,我们收到来自学生和教职工非常热烈而积极的反响,我们意识到卡内基梅隆大学以外的其他人也可以从我们的方法中获益。因此,这本书从ICS课程的笔记中应运而生了,而现在我们对它做了修改,使之能够反映科学技术以及计算机系统实现中的变化和进步。
写给指导教师们:可以基于本书的课程
指导教师可以使用CS: APP这本书来讲授五种不同类型的系统课程(图2)。具体每门课程则有赖于课程大纲的要求、个人品位、学生的背景和能力。图中的课程从左往右,越来越强调以程序员的角度来看待系统。以下是简单的描述:
· ORG:一门以非传统风格讲述传统主题的计算机组成原理课程。传统的主题包括逻辑设计、处理器体系结构、汇编语言和存储器系统。然而,更多地强调对程序员的影响。例如,要反过来考虑数据表示对C语言程序的数据类型和操作的影响。又例如,使用的汇编代码表示是基于C语言编译器产生的机器代码的,而不是手工编写的。
· ORG+:一门特别强调硬件对应用程序性能影响的ORG课程。和ORG课程相比,学生要更多地学习代码优化和改进他们的C语言程序的存储器性能。
· ICS:基本的ICS课程,旨在培养一类程序员,他们能够理解硬件、操作系统和编译系统对应用程序的性能和正确性的影响和ORG+课程的一个显著不同是,本课程不论及低层次的处理器体系结构。相反地,程序员只同现代乱序处理器的高级模型打交道。ICS课程非常适合安排进一个10周的小学期,如果期望步调更从容一些,也可以延长到一个15周的学期。
· ICS+:在基本的ICS课程基础上,额外论述一些系统编程的问题,比如系统级I/O、网络编程和并发编程。这是卡内基梅隆大学的一门一学期长度的课程,会讲述本书中除了低级处理器体系结构以外的所有章。
· SP:一门系统编程课程。和ICS+课程相似,但是剔除了浮点和性能优化的内容,更加强调系统编程,包括进程控制、动态链接、系统级I/O、网络编程和并发编程。指导教师可能会想从其他渠道对某些高级论题做些补充,比如守护进程(daemon)、终端控制和Unix IPC(进程间通信)。
最后,我们认为ORG+和SP课程适合安排为两期(两个小学期或者两个学期)。或者你可以考虑按照一期ICS和一期SP的方式来教授ICS+课程。
经过课堂验证的实验练习
ICS+课程在卡内基梅隆大学得到了学生们很高的评价。学生对这门课的课程评价,中值分数一般为5.0/5.0,平均分数一般为4.6/5.0。学生们说这门课非常有趣,令人兴奋,主要就是因为相关的实验练习。这些实验练习可以从CS: APP的主页上获得。下面是本书提供的一些实验的示例。
· 数据实验。这个实验要求学生实现简单的逻辑和算术运算函数,但是只能使用一个非常有限的C语言子集。比如,他们只能用位级操作来计算一个数字的绝对值。这个实验帮助学生们了解C语言数据类型的位级表示,和数据操作的位级行为。
· 二进制炸弹实验。二进制炸弹是一个作为目标代码文件提供给学生们的程序。运行时,它提示用户输入6个不同的字符串。如果其中的任何一个不正确,炸弹就会“爆炸”,打印出一条错误信息,并且在一个分级(grading)服务器上记录事件日志。学生们必须通过对程序反汇编和逆向工程来测定应该是哪6个串,从而解除他们各自炸弹的雷管。该实验教会学生理解汇编语言,并且强制他们学习怎样使用调试器。
· 缓冲区溢出实验。它要求学生们通过利用一个缓冲区溢出漏洞,来修改一个二进制可执行文件的运行时行为。这个实验教会学生们栈的原理,并让他们了解到写那种易于遭受缓冲区溢出攻击的代码的危险性。
· 体系结构实验。第4章的几个家庭作业问题能够组合成一个实验作业,在实验中,学生们修改处理器的HCL描述,增加新的指令、修改分支预测策略,或者增加或删除旁路路径和寄存器端口。修改后的处理器能够被模拟,并通过运行自动化测试检测出大多数可能的错误。这个实验使学生们能体验到处理器设计中令人激动的部分,而不需要掌握逻辑设计和硬件描述语言的完整的知识。
· 性能实验。学生们必须优化应用程序的核心函数(比如卷积积分或矩阵转置)的性能。这个实验非常清晰地表明了高速缓存的特性,并带给学生们低级程序优化的经验。
· 外壳实验。学生们实现他们自己的带有作业控制的Unix外壳程序,包括ctrl-c和ctrl-z按键、fg、bg和jobs命令。这是学生们第一次接触并发,并且让他们对Unix的进程控制、信号和信号处理有清晰的了解。
· malloc实验。学生们实现他们自己的malloc、free和realloc(可选地)版本。这个实验让学生们清晰地理解数据的布局和组织,并且要求他们评估时间和空间效率的各种权衡和折中。
· 代理实验。学生们实现一个位于浏览器和万维网其他部分之间的并行Web代理。这个实验向学生们揭示了Web客户端和服务器这样的主题,并且联系起了课程中的许多概念,比如字节排序、文件I/O、进程控制、信号、信号处理、存储器映射、套接字和并发。学生们很高兴能够看到他们的程序在真实的web浏览器和web服务器之间起到作用。
CS: APP的教师手册中有对实验的详细讨论,还有关于下载支持软件的说明。
CSAPP目录
出版者的话
译者序
前 言
第1章 计算机系统漫游1
1.1 信息就是位+上下文1
1.2 程序被其他程序翻译成不同的格式3
1.3 了解编译系统如何工作是大有益处的4
1.4 处理器读并解释存储在存储器中的指令5
1.4.1 系统的硬件组成5
1.4.2 运行hello程序7
1.5 高速缓存至关重要7
1.6 存储设备形成层次结构9
1.7 操作系统管理硬件10
1.7.1 进程11
1.7.2 线程12
1.7.3 虚拟存储器12
1.7.4 文件13
1.8 系统之间利用网络通信13
1.9 重要主题15
1.9.1 并发和并行15
1.9.2 计算机系统中抽象的重要性17
1.10 小结17
参考文献说明18
第一部分 程序结构和执行
第2章 信息的表示和处理20
2.1 信息存储22
2.1.1 十六进制表示法22
2.1.2 字25
2.1.3 数据大小25
2.1.4 寻址和字节顺序26
2.1.5 表示字符串31
2.1.6 表示代码31
2.1.7 布尔代数简介32
2.1.8 C语言中的位级运算34
2.1.9 C语言中的逻辑运算36
2.1.10 C语言中的移位运算36
2.2 整数表示38
2.2.1 整型数据类型38
2.2.2 无符号数的编码39
2.2.3 补码编码40
2.2.4 有符号数和无符号数之间的转换44
2.2.5 C语言中的有符号数与无符号数47
2.2.6 扩展一个数字的位表示49
2.2.7 截断数字51
2.2.8 关于有符号数与无符号数的建议52
2.3 整数运算54
2.3.1 无符号加法54
2.3.2 补码加法57
2.3.3 补码的非59
2.3.4 无符号乘法60
2.3.5 补码乘法60
2.3.6 乘以常数63
2.3.7 除以2的幂64
2.3.8 关于整数运算的最后思考67
2.4 浮点数67
2.4.1 二进制小数68
2.4.2 IEEE浮点表示70
2.4.3 数字示例71
2.4.4 舍入74
2.4.5 浮点运算76
2.4.6 C语言中的浮点数77
2.5 小结79
参考文献说明80
家庭作业80
练习题答案90
第3章 程序的机器级表示102
3.1 历史观点103
3.2 程序编码105
3.2.1 机器级代码106
3.2.2 代码示例107
3.2.3 关于格式的注解109
3.3 数据格式111
3.4 访问信息112
3.4.1 操作数指示符112
3.4.2 数据传送指令114
3.4.3 数据传送示例116
3.5 算术和逻辑操作118
3.5.1 加载有效地址118
3.5.2 一元操作和二元操作119
3.5.3 移位操作120
3.5.4 讨论120
3.5.5 特殊的算术操作122
3.6 控制123
3.6.1 条件码124
3.6.2 访问条件码125
3.6.3 跳转指令及其编码127
3.6.4 翻译条件分支129
3.6.5 循环132
3.6.6 条件传送指令139
3.6.7 switch语句144
3.7 过程149
3.7.1 栈帧结构149
3.7.2 转移控制150
3.7.3 寄存器使用惯例151
3.7.4 过程示例152
3.7.5 递归过程156
3.8 数组分配和访问158
3.8.1 基本原则158
3.8.2 指针运算159
3.8.3 嵌套的数组159
3.8.4 定长数组161
3.8.5 变长数组163
3.9 异质的数据结构164
3.9.1 结构164
3.9.2 联合167
3.9.3 数据对齐170
3.10 综合:理解指针172
3.11 应用:使用GDB调试器174
3.12 存储器的越界引用和缓冲区溢出175
3.13 x86-64:将IA32扩展到64位183
3.13.1 x86-64的历史和动因184
3.13.2 x86-64简介185
3.13.3 访问信息187
3.13.4 控制192
3.13.5 数据结构200
3.13.6 关于x86-64的总结性评论200
3.14 浮点程序的机器级表示201
3.15 小结201
参考文献说明202
家庭作业202
练习题答案212
第4章 处理器体系结构230
4.1 Y86指令集体系结构231
4.1.1 程序员可见的状态231
4.1.2 Y86指令232
4.1.3 指令编码233
4.1.4 Y86异常237
4.1.5 Y86程序237
4.1.6 一些Y86指令的详情241
4.2 逻辑设计和硬件控制语言HCL242
4.2.1 逻辑门243
4.2.2 组合电路和HCL布尔表达式243
4.2.3 字级的组合电路和HCL整数表达式245
4.2.4 集合关系248
4.2.5 存储器和时钟248
4.3 Y86的顺序实现250
4.3.1 将处理组织成阶段250
4.3.2 SEQ硬件结构258
4.3.3 SEQ的时序259
4.3.4 SEQ阶段的实现262
4.4 流水线的通用原理267
4.4.1 计算流水线268
4.4.2 流水线操作的详细说明269
4.4.3 流水线的局限性271
4.4.4 带反馈的流水线系统272
4.5 Y86的流水线实现273
4.5.1 SEQ+:重新安排计算阶段273
4.5.2 插入流水线寄存器276
4.5.3 对信号进行重新排列和标号277
4.5.4 预测下一个PC279
4.5.5 流水线冒险280
4.5.6 用暂停来避免数据冒险283
4.5.7 用转发来避免数据冒险285
4.5.8 加载/使用数据冒险288
4.5.9 异常处理289
4.5.10 PIPE各阶段的实现291
4.5.11 流水线控制逻辑297
4.5.12 性能分析305
4.5.13 未完成的工作306
4.6 小结308
参考文献说明309
家庭作业309
练习题答案314
第5章 优化程序性能324
5.1 优化编译器的能力和局限性325
5.2 表示程序性能328
5.3 程序示例330
5.4 消除循环的低效率332
5.5 减少过程调用336
5.6 消除不必要的存储器引用336
5.7 理解现代处理器340
5.7.1 整体操作340
5.7.2 功能单元的性能343
5.7.3 处理器操作的抽象模型344
5.8 循环展开348
5.9 提高并行性351
5.9.1 多个累积变量351
5.9.2 重新结合变换354
5.10 优化合并代码的结果小结358
5.11 一些限制因素359
5.11.1 寄存器溢出359
5.11.2 分支预测和预测错误处罚360
5.12 理解存储器性能363
5.12.1 加载的性能363
5.12.2 存储的性能364
5.13 应用:性能提高技术369
5.14 确认和消除性能瓶颈369
5.14.1 程序剖析370
5.14.2 使用剖析程序来指导优化371
5.14.3 Amdahl定律374
5.15 小结375
参考文献说明375
家庭作业376
练习题答案378
第6章 存储器层次结构382
6.1 存储技术382
6.1.1 随机访问存储器383
6.1.2 磁盘存储389
6.1.3 固态硬盘398
6.1.4 存储技术趋势399
6.2 局部性401
6.2.1 对程序数据引用的局部性402
6.2.2 取指令的局部性403
6.2.3 局部性小结403
6.3 存储器层次结构405
6.3.1 存储器层次结构中的缓存406
6.3.2 存储器层次结构概念小结408
6.4 高速缓存存储器408
6.4.1 通用的高速缓存存储器结构409
6.4.2 直接映射高速缓存410
6.4.3 组相联高速缓存416
6.4.4 全相联高速缓存418
6.4.5 有关写的问题420
6.4.6 一个真实的高速缓存层次结构的解剖421
6.4.7 高速缓存参数的性能影响422
6.5 编写高速缓存友好的代码423
6.6 综合:高速缓存对程序性能的影响426
6.6.1 存储器山426
6.6.2 重新排列循环以提高空间局部性430
6.6.3 在程序中利用局部性433
6.7 小结433
参考文献说明434
家庭作业434
练习题答案442
第二部分 在系统上运行程序
第7章 链接448
7.1 编译器驱动程序449
7.2 静态链接450
7.3 目标文件450
7.4 可重定位目标文件451
7.5 符号和符号表452
7.6 符号解析454
7.6.1 链接器如何解析多重定义的全局符号455
7.6.2 与静态库链接457
7.6.3 链接器如何使用静态库来解析引用460
7.7 重定位461
7.7.1 重定位条目461
7.7.2 重定位符号引用462
7.8 可执行目标文件465
7.9 加载可执行目标文件466
7.10 动态链接共享库467
7.11 从应用程序中加载和链接共享库468
7.12 与位置无关的代码(PIC)471
7.13 处理目标文件的工具473
7.14 小结473
参考文献说明474
家庭作业474
练习题答案479
第8章 异常控制流480
8.1 异常481
8.1.1 异常处理481
8.1.2 异常的类别482
8.1.3 Linux/IA32系统中的异常484
8.2 进程487
8.2.1 逻辑控制流487
8.2.2 并发流487
8.2.3 私有地址空间488
8.2.4 用户模式和内核模式488
8.2.5 上下文切换489
8.3 系统调用错误处理491
8.4 进程控制492
8.4.1 获取进程ID492
8.4.2 创建和终止进程492
8.4.3 回收子进程495
8.4.4 让进程休眠499
8.4.5 加载并运行程序500
8.4.6 利用fork和execve运行程序502
8.5 信号504
8.5.1 信号术语505
8.5.2 发送信号506
8.5.3 接收信号509
8.5.4 信号处理问题511
8.5.5 可移植的信号处理516
8.5.6 显式地阻塞和取消阻塞信号517
8.5.7 同步流以避免讨厌的并发错误517
8.6 非本地跳转521
8.7 操作进程的工具524
8.8 小结524
参考文献说明525
家庭作业525
练习题答案530
第9章 虚拟存储器534
9.1 物理和虚拟寻址535
9.2 地址空间535
9.3 虚拟存储器作为缓存的工具536
9.3.1 DRAM缓存的组织结构537
9.3.2 页表537
9.3.3 页命中538
9.3.4 缺页538
9.3.5 分配页面539
9.3.6 又是局部性救了我们539
9.4 虚拟存储器作为存储器管理的工具540
9.5 虚拟存储器作为存储器保护的工具541
9.6 地址翻译542
9.6.1 结合高速缓存和虚拟存储器544
9.6.2 利用TLB加速地址翻译545
9.6.3 多级页表546
9.6.4 综合:端到端的地址翻译547
9.7 案例研究:Intel Core i7/Linux存储器系统550
9.7.1 Core i7地址翻译551
9.7.2 Linux虚拟存储器系统554
9.8 存储器映射556
9.8.1 再看共享对象557
9.8.2 再看fork函数558
9.8.3 再看execve函数559
9.8.4 使用mmap函数的用户级存储器映射559
9.9 动态存储器分配561
9.9.1 malloc和free函数561
9.9.2 为什么要使用动态存储器分配563
9.9.3 分配器的要求和目标564
9.9.4 碎片565
9.9.5 实现问题565
9.9.6 隐式空闲链表565
9.9.7 放置已分配的块567
9.9.8 分割空闲块567
9.9.9 获取额外的堆存储器567
9.9.10 合并空闲块568
9.9.11 带边界标记的合并568
9.9.12 综合:实现一个简单的分配器570
9.9.13 显式空闲链表576
9.9.14 分离的空闲链表576
9.10 垃圾收集578
9.10.1 垃圾收集器的基本知识579
9.10.2 Mark&Sweep垃圾收集器580
9.10.3 C程序的保守Mark&Sweep580
9.11 C程序中常见的与存储器有关的错误581
9.11.1 间接引用坏指针582
9.11.2 读未初始化的存储器582
9.11.3 允许栈缓冲区溢出582
9.11.4 假设指针和它们指向的对象是相同大小的583
9.11.5 造成错位错误583
9.11.6 引用指针,而不是它所指向的对象583
9.11.7 误解指针运算584
9.11.8 引用不存在的变量584
9.11.9 引用空闲堆块中的数据584
9.11.10 引起存储器泄漏585
9.12 小结585
参考文献说明586
家庭作业586
练习题答案589
第三部分 程序间的交互和通信
第10章 系统级I/O596
10.1 Unix I/O596
10.2 打开和关闭文件597
10.3 读和写文件598
10.4 用RIO包健壮地读写599
10.4.1 RIO的无缓冲的输入输出函数600
10.4.2 RIO的带缓冲的输入函数600
10.5 读取文件元数据604
10.6 共享文件606
10.7 I/O重定向608
10.8 标准I/O609
10.9 综合:我该使用哪些I/O函数610
10.10 小结611
参考文献说明612
家庭作业612
练习题答案612
第11章 网络编程614
11.1 客户端-服务器编程模型614
11.2 网络615
11.3 全球IP因特网618
11.3.1 IP地址619
11.3.2 因特网域名620
11.3.3 因特网连接623
11.4 套接字接口625
11.4.1 套接字地址结构625
11.4.2 socket函数626
11.4.3 connect函数626
11.4.4 open_clientfd函数627
11.4.5 bind函数628
11.4.6 listen函数628
11.4.7 open_listenfd函数628
11.4.8 accept函数629
11.4.9 echo客户端和服务器的示例630
11.5 Web服务器633
11.5.1 Web基础633
11.5.2 Web内容633
11.5.3 HTTP事务634
11.5.4 服务动态内容636
11.6 综合:TINY Web服务器639
11.7 小结645
参考文献说明645
家庭作业646
练习题答案646
第12章 并发编程648
12.1 基于进程的并发编程649
12.1.1 基于进程的并发服务器649
12.1.2 关于进程的优劣651
12.2 基于I/O多路复用的并发编程651
12.2.1 基于I/O多路复用的并发事件驱动服务器653
12.2.2 I/O多路复用技术的优劣657
12.3 基于线程的并发编程657
12.3.1 线程执行模型657
12.3.2 Posix线程658
12.3.3 创建线程659
12.3.4 终止线程659
12.3.5 回收已终止线程的资源660
12.3.6 分离线程660
12.3.7 初始化线程660
12.3.8 一个基于线程的并发服务器661
12.4 多线程程序中的共享变量662
12.4.1 线程存储器模型663
12.4.2 将变量映射到存储器663
12.4.3 共享变量664
12.5 用信号量同步线程664
12.5.1 进度图667
12.5.2 信号量668
12.5.3 使用信号量来实现互斥669
12.5.4 利用信号量来调度共享资源670
12.5.5 综合:基于预线程化的并发服务器674
12.6 使用线程提高并行性676
12.7 其他并发问题680
12.7.1 线程安全680
12.7.2 可重入性682
12.7.3 在线程化的程序中使用已存在的库函数682
12.7.4 竞争683
12.7.5 死锁685
12.8 小结687
参考文献说明687
家庭作业688
练习题答案691
附录A 错误处理694
A.1 Unix系统中的错误处理694
A.2 错误处理包装函数696
参考文献698
1 楼 jinleileiking 2010-10-29 14:05