计算机系统漫游
1.1 信息就是位+上下文
先看一个简单的Hello World C程序。
1 #include <stdio.h> 2 3 void main() 4 { 5 printf("Hello World!\n"); 6 }
这个程序的源文件是文本格式,以字节序列的方式存储在文件中,由一种叫ASCII码的方式编码。除了文本文件之外的其它文件都是二进制文件。
由HelloWorld程序的存储方式可以猜测,信息,包括磁盘文件、内存中运行的程序、内存中储存的用户数据以及通过网络传输的数据,本质上都是一堆bits。区分不同数据的关键在于上下文(context)。在不同的上下文中,同样的字符序列可能代表某个机器指令,或者一个整形数字,或者一个浮点型。
1.2 程序被其它程序翻译成不同格式
从HelloWorld源程序到可执行程序之间大致经过以下几个阶段:
#预处理阶段(preprocessor):根据以#开头的宏命令修改原始程序的内容。例如根据#include <stdio.h>将stdio.h的内容插入程序。输出结果还是文本程序。
#编译阶段(compiler):输出一个汇编语言程序,汇编语言为不同的高级编程语言提供了一种通用的输出语言,这是很有用的。本阶段
输出格式依然是文本文件。
#汇编阶段(assembly):汇编器将上一阶段的结果翻译成机器语言,生成一个二进制文件称为“可重定位目标程序(relocatable object program)”。
#链接阶段(linker):由于HelloWorld程序调用了printf函数,而该函数包含在由编译器提供的C标准函数库里面。链接阶段所做的就是将包含printf函数的printf.o文件以某种方式和上一阶段的hello.o合并,结果就得到可执行文件hello,可以被加载到内存中,由系统执行。
1.3 了解编译系统如何工作是大有益处的
什么是链接错误?While循环和for循环哪个更有效?通过了解编译等方面的知识我们将能回答类似的问题,从而使编程更高效。
1.4 处理器读取并解释存储在内存中的命令
一个典型的系统由哪些硬件组成?
#总线(bus):总线负责信息在各个部件之间的传递。信息在总线中以定长的方式传递,也就是字(word)。字中的字节数是系统的基本参数之一。大多数机器的字长是4个字节(32位),有的机器字长是8个字节(64位)。
#输入输出设备(I/O):输入输出设备是系统与外界联系的通道。通常一个I/O设备不是适配器(adapter)就是控制器(controller),区别在于adapter是插到卡槽中的,而controller是I/O设备本身或主板上的芯片组。比如显示设备是adapter,而键盘鼠标和硬盘则是controller。在系统的角度来说,网络(network)也是一种I/O。
#主存(main memory):主存是一个临时储存设备,在处理器执行程序时用来储存程序和程序的数据。
#处理器(CPU):中央处理单元,简称处理器,是解释存储在主存中指令的引擎。从系统通电开始,到系统断电,处理器一直在不断的执行计数器(PC)指向的指令,再更新计数器,使其指向下一条指令。CPU的操作是围绕主存、寄存器文件(register file)、ALU进行的。寄存器文件是一个小的存储设备,由一系列1字长的寄存器组成,每个存储器都有唯一的名字。ALU(算数/逻辑单元)计算新的数据和地址值。CPU在指令的要求下可能执行以下动作:、
~加载:把一个字节或一个字从主存复制到寄存器,以覆盖寄存器原来的内容。
~存储:把一个字节或一个字从寄存器复制到主存的某个地方,以覆盖这个地方原来的内容。
~操作:把两个寄存器的内容复制到ALU,对这两个字进行算数操作,并将结果存在一个寄存器中,覆盖原来的内容。
~跳转:从指令中取出一个字,并将这个字复制到程序计数器(PC)中,覆盖原来的内容。
1.5 高速缓存至关重要
一个典型系统上的磁盘可能比主存大一千倍,但是从磁盘读取数据的速度可能比从主存读取数据的速度慢一千万倍。处理器从主存中读取文件的速度比从主存中读取的速度又快了几乎一百倍。而且让处理器运行的更快比让主存运行的更快要便宜的多。针对这种情况,系统设计者采用了更小、更快速的存储设备,也就是告诉缓存。L1缓存运行最快,但是容量最小。L3缓存运行较慢,但是容量较大。这些缓存的读取速度都比主存快很多。意识到高速缓存存在的程序员能够利用它们使得程序的性能大大提升。
1.6 存储设备层次结构
在存储器的层次结构中,CPU寄存器位于顶端,其次是三级缓存,然后是主存、本地磁盘,甚至是远程存储。存储器的层次结构的主要思想是上一级的存储器作为下一集的存储器的高速缓存。例如,寄存器是L1的高速缓存,L1-L3则是主存的高速缓存,主存则是硬盘的高速缓存。程序员同样可以利用队存储器层次结构的理解来提高程序的性能。
1.7 操作系统管理硬件
应用程序不会直接访问I/O和主存等设备。它们依靠操作系统提供的服务。我们可以把操作系统看做是应用程序和硬件之间的一层软件。应用程序对硬件的所有操作尝试都必须经过操作系统。
操作系统有两个基本功能:
1、防止硬件被失控的程序滥用。
2、为应用程序提供简单一直的机制来控制复杂多变的底层硬件设备。
操作系统通过一系列抽象来完成目标。文件是对I/O设备的抽象。虚拟存储器是对主存、磁盘存储器的抽象。进程(process)是对处理器、I/O和存储器的抽象。
进程是计算机对一个应用程序的一种抽象,在一个系统上可以同时运行多个进程,每个进程都好像在独占硬件。并发运行,说的是一个进程的指令和另一个进程的指令是交错执行的。操作系统在不同的进程中保存各自的上下文(context),这种交错执行的机制称为上下文切换。
在现代系统中,一个进程实际上可以由多个称为线程的执行单元组成。每个线程都运行在进程的上下文中,共享同样的代码和全局数据。
虚拟存储器是一个抽象概念,它为每一个进程提供了一个假象,即每个进程都在独占的使用内存。每个进程看到的是一致的存储数据,称为虚拟地址空间。下图是Linux进程的虚拟地址空间。
注意地址从下往上逐渐增大。
#程序代码和数据:对所有进程来说,代码从同一固定地址开始。代码和数据区按照可执行目标文件的数据来进行初始化。
#堆(heap):代码和数据区在程序运行时就规定了大小,而堆则可以在运行时动态的收缩,如调用malloc和free等时。
#共享库(shared libiaries):存放C标准库和数学库等共享库的地方。
#栈(stack):编译器用它来实现函数调用。栈的大小也是运行期动态收缩的。当我们调用一个函数它就增大,函数返回时它就收缩。
#内核虚拟存储器(kernel virtual memory):内核总是在内存中,是操作系统的一部分。顶部区域是为内核保留,不允许应用程序使用或直接调用内核中定义的函数。
虚拟存储器的基本思想是把一个程序的虚拟存储器的内容存储在磁盘上,然后使用主存作为磁盘的高速缓存。
文件就是字节序列。每个I/O设备,包括磁盘、键盘鼠标、显示器,甚至网络,都可以看做文件。文件响应用程序提供了一个统一的视角来看待各种不同的I/O设备。程序可以不关系具体的磁盘技术而处理磁盘文件内容,同一个程序可以在使用不同磁盘技术的不同系统上运行。
1.8 系统之间利用网络通信
系统通过网络和其它系统连接在一起。在单独的系统来看,网络可以视为一个I/O设备。
1.9 重要主题
并发和并行。术语并发(concurrency)指的是同时具有多个活动的系统。并行(parallelism)指的是用并发使系统运行的更快。
#线程级并发:使用线程,我们能够在一个线程中执行多个控制流。传统意义上的并发还是快速在多个正在执行的进程中切换来实现的。由一个处理器来进行运算的系统称作单处理器系统。由但操作系统内核控制的多处理器系统称为多处理器系统。实现多处理器系统可以通过多核(multi-core)或超线程(hyper-threaded)。
多核处理器是将多个CPU(称为“核”)集成到一个集成电路芯片上。
超线程,是一项允许一个CPU执行多个控制流的技术。它涉及CPU某些硬件具有多个备份,如PC和寄存器;而其他硬件只有一份,如执行浮点算数运算的单元。常规处理器大约需要2000个clock cycle来执行不同线程之间的转换,而超线程的处理器可以在单个周期的基础上决定要执行哪个线程。如果一个核可以执行两个线程,那么一个四核的系统可以并行的执行8个线程。
#指令级并行
在较低的抽象层级上,现代处理器可以并行的执行多条指令,称为指令级并行。如果一个处理器可以达到比一个周期一条指令更快的操作,那么久称为超标量(superscalar)处理器。大多现代处理器都支持超标量操作。
#单指令、多数据并行
在最低层次上,许多现代处理器拥有特殊硬件,允许一条指令产生多个可以并行执行的操作,称为单指令、多数据。
1.10 小结
计算机内部的信息被表示为一组组的位,他们依据上下文有不同的解释方式。程序被其它程序翻译为不同的形式,最开始是ASCII文本,然后被编译器和链接器翻译成二进制可执行文件。
处理器读取并解释存放在主存里的二进制指令。因为计算机花费大量时间用来在存储器、I/O设备和CPU寄存器之间复制数据,所以将系统中的存储设备划分成层次结构——寄存器在顶部,然后是高速缓存、主存和磁盘。在存储器层次结构中,位于更高位置的存储器比低层位置的存储器更快,单位比特的开销也更高。较高层次的存储设备为较低层次的存储设备提供高速缓存。
操作系统内核是硬件和应用程序之间的抽媒介。它提供了三个基本抽象:文件是I/O设备的抽象,虚拟存储器是对主存和磁盘的抽象,进程是对处理器、主存和I/O设备的抽象。
网络提供了计算机系统间的通讯手段。从单个系统的角度看,网络就是一种I/O设备。