深入理解计算机系统 第一章 计算机系统漫游
本着对计算机运行原理的好奇以及个人职业发展的需要,开始阅读这本书。
以下分节记录读书笔记:
1.1 信息就是位 + 上下文
计算机系统中存放的所有信息都是由一串比特(bit)表示的,但值得注意的是,同样的比特信息在不同的上下文中所代表的意思是不同的。
在这里,我们可以将“上下文”理解为对比特信息的解读方式。每一个解读方式,都有其独特的解读规则。例如,某个字节的整数值为 47,在上下文 A 中,它被解读为“可以”,在上下文 B 中,它被解读为“桌子”。
注:此处可以类比对文本的加密解密来理解。
1.2 程序被其他程序翻译成不同的格式
计算机执行程序的过程可以理解为,计算机读取人类的命令,并执行它。
而计算机对信息的读取方式和人类的相差很大,最好的办法当然是创造一种语言,让人类和计算机都能轻易读懂,并且人类能够很轻易的书写。
但是目前这种语言还没有诞生,目前的处理方法是,人类书写对于人类思维比较友好的代码,经过几类特定程序的翻译,将其变为计算机能够读懂并执行的命令。这几类特定的程序在业界中分别被称呼为预处理器、编译器、汇编器和连接器,这 4 个阶段的程序一起构成了编译器。
翻译流程如下图:(图片来自于《深入理解计算机系统》第 3 版第一章)
1.3 了解编译系统如歌工作是大有益处的
编译系统帮助我们将程序翻译成计算机容易理解并且能够执行的机器代码,我们可以不了解编译系统的工作原理,直接使用。
但如果了解了它的工作原理,将带来以下 3 个好处:
1、优化程序性能
了解一些机器代码以及编译器将不同的高级语言代码转化为机器代码的方式,可以帮助我们在程序中做出更好的编码选择,从而提高代码执行效率
2、理解链接时出现的错误
据专业人士的经验,一些最令人困扰的程序错误往往都与链接器操作有关,由其当我们试图构建大型的软件系统时。
3、避免安全漏洞
缓冲区溢出错误时造成大多数网络和 Internet 服务器上安全漏洞的主要原因,我们要能够理解从不受信任的源接收数据的数量和格式,才能有效避免这些安全漏洞。
1.4 处理器读并解释储存在内存中的指令
当程序被编译器翻译成了可执行的目标文件之后,要想在 Unix/Linux 系统上运行时,可将其名称输入到一个 shell 的应用程序中
例如:linux> ./hello
shell 是一个命令行解释器,它输出一个提示符,等待输入一个命令行,然后执行这个命令。
1.4.1 系统的硬件组成
系统的硬件由 4 个部分组成:总线、I/O 设备、主存和处理器。
1.4.2 运行 hello 程序
shell 程序执行指令,将其读入寄存器,并放入主存。然后,处理器会执行主存中的 hello 程序的 main 程序中的机器语言指令。这些指令将 “hello,world\n” 字符中字节从主存复制到寄存器,在从寄存器文件中复制到显示设备,最终显示在屏幕上。
1.5 高速缓存至关重要
通过上述示例我们可以知道,系统花费了大量的时间把信息从一个地方搬运到另一个地方。
由于处理器对数据的处理速度远大于主存,若处理器直接从主存中读取数据,则处理器的性能会被大大的浪费掉。
此时,高速缓存应运而生,利用高速缓存的局部性原理,存放处理器近期可能会需要的信息,使得大部分的内存操作都能在快速的高速缓存中完成。
1.6 存储设备形成层次结构
在处理器和一个较大较慢的设备(例如主存)之间插入一个更小更快地存储设备(例如高速缓存)的想法已经成为一个普遍的概念。
实际上,每个计算机系统中的存储设备都被组织成了一个存储器层次结构,如下图所示:
存储器层次结构的主要思想是上一层的存储器作为低一层存储器的高速缓存。
程序员可以利用对整个存存储器层次结构的理解来提高程序性能。
1.7 操作系统管理硬件
操作系统是应用程序和硬件之间的一层软件,所有应用程序对硬件的操作尝试都必须通过操作系统。
操作系统有两个基本的功能:(1)防止硬件被失控的应用程序滥用;(2)向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。
操作系统通过几个基本的抽象概念(进程、虚拟内存和文件)来实现这两个功能。
文件是对 I/O 设计的抽象,虚拟内容是对主存和磁盘 I/O 设备的抽象,进程是对处理器、主存和 I/O 设备的抽象。
1.8 系统之间利用网络通信
每个系统都是一个孤立的个体,而系统要想与其他系统之间进行通信,则可以通过网络。网络可以将各个系统串联起来。
可以将网络视为一个磁盘,与网络交换数据,和与磁盘交互数据本质上是一样的。