CSAPP_第一章:计算机系统漫游读书笔记
一、信息的本质:位 + 上下文
计算机系统中的所有信息都以0和1的位序列形式存在,这些信息可以是代码、数据或网络数据包等。它们的区别取决于具体的使用场景(上下文)。例如,0xCC在代码中能够代表int 3指令,而在hello.c的ASCII文本中,字节值35则对应着字符#。这就说明一个问题,程序的可读性是给人看的,计算机只认位序列。这也解释了日常遇到的乱码文件,本质来讲是上下文错误。
二、程序的生命周期:编译系统四阶段
从hello.c源文件到可执行文件,需要经历四个阶段:
- cpp处理#include等指令替换为实际内容,生成.i文件。比如,#include <stdio.h>会插入标准输入输出库的代码。
- cc1将高级代码转为汇编语言(如hello.s),此时已经接近机器语言,但是仍然为文本格式。
- as将汇编指令转为二进制目标代码,生成.o文件。此时机器已经识别了这些指令,但是还需要链接外部的依赖。
- ld将hello.o与printf.o等库文件合并,生成最终的可执行文件。
三、硬件协作:程序如何运行
当执行./hello时,硬件和OS步骤如下:
- 输入命令:键盘输入./hello,字符先存入寄存器,再写入内存。
- 加载程序:通过DMA技术,hello的代码和数据从磁盘直接复制到主存,无需CPU参与。
- 执行指令:CPU从主存读取并执行命令,将"hello, world\n"从内存复制到寄存器,在输出到显示器。
四、高速缓存与存储层次
处理器速度远超过主存的速度,这也就是引出了Cache技术。
- L1/L2/L3缓存:SRAM实现,容量递增,速度递减
- 局部性原理:程序倾向于访问临近数据,缓存会预取相邻的数据块,提前加载潜在的内容。
存储层次如下所示:
五、操作系统抽象
- 进程:程序运行的隔离环境(如hello与shell并发),上下文切换由OS的内核决定:
- 线程:进程内的独立执行单元,运行在进程上下文中,与同进程的其他线程共享代码、全局数据、堆内存、文件描述符等资源;但每个线程有自己的寄存器、栈空间、局部变量(线程私有数据)
- 虚拟内存:每个进程都可以看到连续内存空间,实际是磁盘与主存的结合体。内存布局从低到高依次为:代码段、数据段、堆、共享库、栈。其进程的内存布局如下所示:
- 文件:对于I/O设备的抽象,让磁盘、键盘、网络等都能用统一的读写接口操作。
六、Amdahl定律
- 该定律表明系统提升的上限,由不可优化的部分决定。
七、并发与并行
- 并发:多个任务交替执行(如单CPU上的多进程切换)。
- 并行:多个任务同时执行(如多核CPU上的多线程)。
系统在三个层次支持并行:
- 线程级并行:多线程共享进程资源,比多进程更高效。
- 指令级并行:现代CPU能同时执行多条指令(超标量处理器)。
- SIMD 并行:单条指令处理多个数据,适合图像、视频等场景。