📕书籍信息
- 书名:深入理解计算机系统(原书第2版)
- 作者:[美] Randal E.Bryant,[美] David O' Hallaron
- 豆瓣评分:⭐9.7
- 出版社:机械工业出版社
- isbn:9787111321330
- 出版日期:2011-1-1
- 价格:99.00元
- 豆瓣:深入理解计算机系统(原书第2版)
🌵内容简介
【编辑推荐】:
本书从程序员的视角详细阐述计算机系统的本质概念,并展示这些概念如何实实在在地影响应用程序的正确性、性能和实用性。全书共12章,主要内容包括信息的表示和处理、程序的机器级表示、处理器体系结构、优化程序性能、存储器层次结构、链接、异常控制流、虚拟存储器、系统级I/O、网络编程、并发编程等。书中提供大量的例子和练习,并给出部分答案,有助于读者加深对正文所述概念和知识的理解。
本书的最大优点是为程序员描述计算机系统的实现细节,帮助其在大脑中构造一个层次型的计算机系统,从最底层的数据在内存中的表示到流水线指令的构成,到虚拟存储器,到编译系统,到动态加载库,到最后的用户态应用。通过掌握程序是如何映射到系统上,以及程序是如何执行的,读者能够更好地理解程序的行为为什么是这样的,以及效率低下是如何造成的。
本书适合那些想要写出更快、更可靠程序的程序员阅读,也适合作为高…
📣听过的人说…
- 👽: 从编译原理角度来思考这本书特别有意义!三个不容易理解的地方就特别好思考:汇编:函数调用—栈式计算机;链接—构建符号表;多线程—非确定性状态机。
- 👻: 别的教材没见有把2的补码讲得这么清楚的
- 👻: 值得翻来覆去读100遍的好书,为啥要读那么多遍呢?因为反复都读不很懂啊。。。
🧐讀書筆記 –
这大概是自己人生买的第一本厚厚的计算书了,而自己学的却是电子信息,许多原理到数电模电这来自己是可以理解的。
但这本书对于自己的意义从不在于技术上的领悟,而是在搭了一座桥连接了自己和现实世界,我终于明白从零到有是什么样的情况。也终于明白规则的重要性,标准的重要性,有了规则有了标准,一切都可以从无到位。
仅仅是零和一两个的存在,就构建出了而今的信息世界。直到自己后来读心理,哲学,这本书对于自己的影响还在,许多技术细节,模样甚至大纲都记不清了 。但那种从无到位,一步一步搭建,每一…
📑书籍章节
- 出版者的话
- 译者序
- 前 言
- 第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
评论(0)