深入理解计算机系统(第2版)- CS:APP
核心信息
- 书名: Computer Systems: A Programmer’s Perspective (CS:APP)
- 作者: Randal E. Bryant, David R. O’Hallaron
- 出版社: Prentice Hall (Carnegie Mellon University)
- 版本: 第2版,2011年
- 页数: 1078页
- 分类: 计算机系统基础经典教材
本书简介
这是一本从程序员视角出发讲解计算机系统的经典教材。与传统的”构建者视角”教材不同,本书专注于帮助程序员理解系统内部工作原理,从而写出更好的程序。
“Other systems books are written from a builder’s perspective… This book is written from a programmer’s perspective.”
作者是卡内基梅隆大学15-213课程的教师,该书是这门著名课程的配套教材。
全书结构
Part I: Program Structure and Execution(程序结构与执行)
| 章节 | 标题 | 核心内容 |
|---|---|---|
| Ch 1 | A Tour of Computer Systems | 计算机系统概览:信息、程序翻译、缓存、存储层次、操作系统、网络 |
| Ch 2 | Representing and Manipulating Information | 数据存储:十六进制、无符号/补码整数、浮点数、位级操作、布尔代数 |
| Ch 3 | Machine-Level Representation of Programs | 机器级代码:x86-64汇编、数据格式、寻址方式、控制流、过程调用、指针 |
| Ch 4 | Processor Architecture | 处理器架构:Y86指令集、逻辑设计、流水线、冒险处理、性能分析 |
| Ch 5 | Optimizing Program Performance | 性能优化:循环优化、并行性增强、寄存器溢出、分支预测、剖析工具 |
| Ch 6 | The Memory Hierarchy | 内存层次结构:RAM、磁盘、SSD、局部性、Cache组织、亲和性编码 |
Part II: Running Programs on a System(在系统上运行程序)
| 章节 | 标题 | 核心内容 |
|---|---|---|
| Ch 7 | Linking | 链接:静态链接、目标文件、符号解析、重定位、动态链接、共享库、PIC |
| Ch 8 | Exceptional Control Flow | 异常控制流:异常分类、进程控制、信号处理、非局部跳转 |
| Ch 9 | Virtual Memory | 虚拟内存:物理/虚拟地址、页表、TLB、多级页表、地址翻译、内存映射、垃圾回收 |
| Ch 10 | System-Level I/O | 系统级I/O:Unix I/O、文件操作、Rio包、文件元数据、标准I/O |
| Ch 11 | Network Programming | 网络编程:客户端-服务器模型、IP地址、域名系统、Socket接口、Web服务器 |
| Ch 12 | Concurrent Programming | 并发编程:进程并发、I/O多路复用、POSIX线程、同步原语、死锁 |
核心知识点笔记
1. 信息即比特 + 上下文(Ch 1.1)
同一串二进制位在不同上下文中可以表示不同类型的数据:
- 整数(补码表示)
- 浮点数(IEEE 754)
- 字符(ASCII/UTF-8)
- 机器指令
- 指针
启示:程序的正确性取决于如何解释内存中的比特。
2. 程序被翻译成不同的形式(Ch 1.2)
程序生命周期:
源代码 → 预处理器 → 编译器 → 汇编器 → 目标文件 → 链接器 → 可执行文件
关键点:理解翻译过程有助于:
- 调试编译错误
- 理解链接错误
- 编写可移植代码
3. 整数表示与运算(Ch 2.2)
无符号编码(B2U):
- 值 = Σ xᵢ · 2ⁱ
- 范围:[0, 2ʷ-1]
- 每个值有唯一的二进制表示
补码编码(B2T):
- 值 = -x_{w-1}·2^{w-1} + Σ xᵢ·2ⁱ(i从0到w-2)
- 范围:[-2^{w-1}, 2
- 负数的最高有效位为1
重要性质:
- 补码和無符号数使用相同的加法电路
- 负零不存在(无符号数才有)
- C中
unsigned和signed的转换容易引发bug
4. 浮点数表示(Ch 2.4)
IEEE 754单精度(32位):
- 1位符号位
- 8位指数(偏置127)
- 23位尾数
双精度(64位):
- 1位符号
- 11位指数(偏置1023)
- 52位尾数
关键概念:
- 规格化数:隐含前导1
- 非规格化数:处理下溢
- 特殊值:Inf、NaN
5. 机器级表示与x86-64(Ch 3)
寻址模式:
- 立即数:
$0x5 - 寄存器:
%rax - 直接寻址:
0x100 - 间接寻址:
(%rax) - 变址寻址:
0x8(%rbx, %rax, 4)
栈帧结构:
- 参数传递(前6个通过寄存器:%rdi, %rsi, %rdx, %rcx, %r8, %r9)
- 局部变量分配
- 对齐要求(16字节)
常见bug:缓冲区溢出、悬空指针、内存泄漏
6. 处理器架构与流水线(Ch 4)
流水线阶段(Y86):
- IF - 取指
- ID - 译码/读寄存器
- EX - 执行/计算地址
- MEM - 访问内存
- WB - 写回寄存器
流水线冒险:
- 结构冒险:资源冲突
- 数据冒险:需要等待前一条指令结果
- 控制冒险:分支预测失败
解决方案:
- 停顿(stall)
- 前递(forwarding)
- 分支预测
7. 性能优化原则(Ch 5)
关键优化技术:
- 消除循环开销(循环展开)
- 减少过程调用
- 消除不必要的内存引用
- 理解函数依赖关系
- 增强并行性(多个累加器)
Amdahl定律:
加速比 = 1 / [(1-f) + f/s]
- f: 可加速部分占比
- s: 加速倍数
- 即使无限加速,整体提升也受限于未加速部分
8. 内存层次结构(Ch 6)
层次结构(从上到下):
- 寄存器(最快)
- L1 Cache(约1周期)
- L2 Cache
- L3 Cache
- 主存(DRAM)
- 磁盘
- 远端服务器
局部性原理:
- 时间局部性:刚访问的数据很可能再次访问
- 空间局部性:附近的数据很可能被访问
Cache友好编码:
- 按行优先遍历二维数组
- 利用数组的连续内存布局
- 避免不必要的缓存失效
9. 链接过程(Ch 7)
目标文件格式(ELF):
- 代码段(.text):机器指令
- 数据段(.data):已初始化的全局变量
- BSS段(.bss):未初始化的全局变量
- 符号表
- 重定位表
静态链接:
- 合并所有目标文件
- 解析符号引用
- 生成可执行文件
动态链接:
- 共享库(.so)
- 延迟绑定(lazy binding)
- 位置无关代码(PIC)
10. 异常控制流(Ch 8)
异常类型:
- 中断:来自I/O设备
- 陷阱:由指令引发(系统调用、异常)
- 故障:可恢复的错误
- 中止:不可恢复的错误
进程管理:
- fork:创建子进程
- execve:加载并运行程序
- waitpid:等待子进程结束
信号机制:
- 发送信号(kill)
- 捕获信号
- 阻塞/取消阻塞
11. 虚拟内存(Ch 9)
关键抽象:
- 隔离:每个进程有自己的地址空间
- 共享:多个进程可共享同一内存
- 层次化:利用局部性管理内存
- 持久化:内存与磁盘的映射
地址翻译:
虚拟地址 → TLB/页表 → 物理地址
关键机制:
- 页表(多级)
- TLB(快表)
- 缺页异常
- 页面替换算法(LRU等)
- 内存映射(mmap)
malloc实现:
- 隐式空闲链表
- 边界标签(boundary tags)
- 分离空闲列表
12. 系统级I/O(Ch 10)
Unix I/O模型:
- 文件描述符
- open/close
- read/write
- lseek(文件定位)
Rio包(robust I/O):
- rio_readinitb:初始化缓冲输入
- rio_readnb:无缓冲读取(精确n字节)
- rio_readlineb:缓冲读取一行
13. 网络编程(Ch 11)
套接字接口:
socket() // 创建套接字
bind() // 绑定地址
listen() // 监听连接
accept() // 接受连接
connect() // 发起连接Web服务器模型:
- 单进程服务器
- 迭代服务器
- 并发服务器(fork/线程/IO多路复用)
14. 并发编程(Ch 12)
并发模型:
- 基于进程的并发:每个客户端一个进程
- 基于IO多路复用的并发:单进程处理多个连接
- 基于线程的并发:轻量级进程共享地址空间
同步原语:
- 互斥量(mutex)
- 信号量(semaphore)
- 条件变量(condition variable)
常见问题:
- 竞态条件(race condition)
- 死锁(deadlock)
- 活锁(livelock)
- 饥饿(starvation)
实践要点
- 使用gdb调试:查看汇编级别代码、设置断点、检查寄存器
- 关注类型转换:特别是signed/unsigned混合运算
- 理解栈帧:手动画出调用栈有助于调试
- 注意对齐:数据对齐影响性能和正确性
- 利用局部性:代码结构影响缓存命中率
- 小心并发:使用合适的同步原语避免竞态
与其他书籍的关联
- The-C-Programming-Language-4th-Edition-Bjarne-Stroustrup - C语言基础
- SICP-计算机程序的构造和解释-Harold-Abelson - 计算过程抽象
- LINUX内核源代码情景分析-李强 - Linux内核实现细节
- C++-Concurrency-in-Action-2nd-Edition - C++并发编程
总结
CS:APP是计算机系统入门的绝佳教材,特点:
- 程序员视角:关注”如何使用系统知识写出更好的程序”
- 层次化讲解:从比特到应用,循序渐进
- 理论与实践结合:有大量实验项目(Bomb Lab、Shell Lab等)
- 覆盖全面:涵盖硬件、系统软件、应用程序的完整栈
适合读者:
- 想深入理解系统底层原理的程序员
- CS专业的本科生
- 准备系统面试的技术人员
本笔记基于《Computer Systems: A Programmer’s Perspective》第2版整理