①、程序员通过文本编辑器创建并保存的文本文件,命名为hello.c
1.1 信息就是位+上下位
源程序实际上就是一个由0和1组成的位(又称为比特)序列,8个位被组织成一组,称为字节。
每个字节表示程序中的某些文本字符。
注意:每个文本行都是以一个看不见的换行符‘
’来结束的,它所对应的整数值为10。
像hello.c这样只由ASCII字符构成的文件称为文本文件,所有其他文件都被称为二进制文件。
hello.c的表示方法说明一个基本思想:系统中所有的信息——包括磁盘文件、内存中的程序、
内存中存放的用户数据以及网络上传送的数据,都是由一串比特表示的。
区分不同数据对象的唯一方法是我们读到这些数据对象时的上下文。
1.2 程序被其他程序翻译成不同的格式
程序代码 ——————> 目标程序(可执行目标文件)
通过编译系统
在这个过程中,要执行四个阶段的程序(预处理器、编译器、汇编器和链接器),
这四者一起构成编译系统(compilation system)。
1.3 了解编译系统如何工作是大有益处的
1.4 处理器读并解释储存在内存中的指令
1. 4.1 系统的硬件组成
- 总线
贯穿这个系统的一组电子管道,称为总线,它携带信息字节并负责在各个部件间传递。
通常总线被设计成传送定长的字节快,也就是字(word)。
- I/O设备
每个I/O设备都通过一个控制器或适配器与I/O总线相连。
控制器与适配器的区别主要在于它们的封装方式。
控制器是I/O设备本身或者系统的主印制电路板(通常称作主板)上的芯片组。
而适配器则是一块插在主板插槽上的卡。
无论如何,它们的功能都是在I/O总线和I/O设备之间传递信息。
- 主存
主存是一个临时存储设备,在处理器执行程序时,用来存放程序和程序处理的数据。
从物理上来说,主存是由一组动态随机存取存储器(DRAM)芯片组成的。
从逻辑上来说,存储器是一个线性的字节数组,每个字节都有其唯一的地址(数组索引),这些地址是从零开始的。
- 处理器
中央处理器(CPU),简称处理器,是解释(或执行)存储在主存中指令的引擎。
处理器的核心是一个大小为一个字的存储设备(或寄存器),称为程序计数器(PC)。
在任何时刻,PC都指向主存中的某条机器语言指令(即含有该条指令的地址)。
指令集架构 && 微体系结构
指令集架构描述的是每条机器代码指令的效果;
微体系结构描述的是处理器实际上是如何实现的。
1.4.2 运行hello程序
初始时,shell程序执行它的指令,等待我们输入一个命令。
当我们在键盘上输入字符串“./hello”后,shell程序将字符逐一读入寄存器,再把它存放到内存中,如图1-5所示。
当我们在键盘上敲回车键时,shell程序就知道我们已经结束了命令的输入。然后
shell执行一系列指令来加载可执行的hello文件,这些指令将hello目标文件中的代码和
数据从磁盘复制到主存。数据包括最终会被输出的字符串“hello, world
”。
利用直接存储器存取(DMA,将在第6章中讨论)技术,数据可以不通过处理器而直
接从磁盘到达主存。这个步骤如图1-6所示。
一旦目标文件hello中的代码和数据被加载到主存,处理器就开始执行hello程序
的main程序中的机器语言指令。这些指令将“hello,world
”字符串中的字节从主存
复制到寄存器文件,再从寄存器文件中复制到显示设备,最终显示在屏幕上。这个
步骤如图1-7所示。
1.5 高速缓存至关重要
针对处理器与主存之间的差异,系统设计者采用了更小更快的存储设备,称为高速
缓存存储器(cache memory,简称为cache或高速缓存),作为暂时的集结区域,存放处
理器近期可能会需要的信息。
图1-8展示了一个典型系统中的高速缓存寄存器。
L1和L2高速缓存是用一种叫做静态随机访问存储器(SRAM)的硬件技术实现的。
高速缓存的局部性原理,即程序具有访问局部区域里的数据和代码的趋势。
1.6 存储设备形成层次结构
1.7 操作系统管理硬件
如图1-10所示。所有应用程序对硬件的操作尝试都必须通过操作系统。
操作系统有两个基本功能:
(1)防止硬件被失控的应用程序滥用;
(2)向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。
操作系统通过几个基本的抽象概念(进程、虚拟内存和文件)来实现这些功能。
如图1-11所示,文件是对I/O设备的抽象表示,虚拟内存是对主存和磁盘I/O设备的抽象表示,
进程则是对处理器、主存和I/O设备的抽象表示。
1.7.1 进程
进程是操作系统对一个正在运行的程序的一种抽象。
并发运行,则是说一个进程的指令和另一个进程的指令是交错执行的。
无论是单核还是多核系统中,一个CPU看上去都像是在并发地执行多个进程,
这是通过处理器在进程间切换来实现的。操作系统实现这种交错执行的机制称为
上下文切换。
操作系统保持跟踪进程运行所需的所有状态信息。这种状态,也就是上下文,包括
许多信息,比如PC和寄存器文件的当前值,以及主存的内容。
图1-12展示了示例hello程序运行场景的基本理念。
如图1-12所示,从一个进程到另一个进程的转换是由操作系统内核(kernel)管理的。
内核是操作系统代码常驻主存的部分。
注意,内核不是一个独立的进程。相反,它是系统管理全部进程所用代码和数据结构的集合。
实现进程这个抽象概念需要低级硬件和操作系统软件之间的紧密合作。
1.7.2 线程
尽管通常我们认为一个进程只有单一的控制流,但是在现代系统中,一个进程实际上
可以由多个称为线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的
代码和全局数据。
由于网络服务器中对并行处理的需求,线程称为越来越重要的编程模型,因为多线程
之间比多进程之间更容易共享数据,也因为线程一般来说都比进程更高效。
1.7.3 虚拟内存
虚拟内存是一个抽象概念,它为每个进程提供了一个假象,即每个进程都在独占地使用
主存。每个进程看到的内存都是一致的,称为虚拟地址空间。
图-13所示的是Linux进程的虚拟地址空间(Unix系统的设计也与此类似)。
在Linux中,地址空间最上面的区域是保留给操作系统中的代码和数据的,这对所有进程
来说都是一样。地址空间的底部区域存放用户进程定义的代码和数据。
请注意,图中的地址是从下往上增大的。
从最低的地址开始,逐步向上结束。
- 程序代码和数据。
- 堆
- 共享库
- 栈
- 内核虚拟内存
1.7.4 文件
文件就是字节序列,仅此而已。
每个I/O设备,包括磁盘、键盘、显示器,设置网络,都可以看成是文件。
系统中的所有输入输出都是通过使用一小组称为Unix I/O的系统函数调用读写文件来实现的。
文件这个简单而精致的概念是非常强大的,因为它向应用程序提供了一个统一的视图,来对
待系统中可能含有的所有各式各样的I/O设备。
1.8 系统之间利用网络通信
网络也是一种I/O设备
我们可以使用熟悉的telnet应用在一个远程主机上运行hello程序。
1.9 重要主题
系统不仅仅只是硬件。系统是硬件和系统软件互相交织的集合体,它们必须共同协作以达
到运行应用程序的最终目的。
1.9.1 Amdahl定律
Amdahl定律的主要观点——要想显著加速整个系统,必须提升全系统中相当大的部分的速度。
1.9.2 并发和并行
我们的术语
并发(concurrency)是一个通用的概念,指一个同时具有多个活动的系统;
并行(parallelism)指的是用并发来使一个系统运行得更快。
并行可以在计算机系统的多个抽象层次上运用。在此,我们按照系统层次结构中由高到低的顺序
重点强调是哪个层次。
- 线程级并发
传统意义上,这种并发执行只是模拟出来的,是通过使一台计算机在它正在执行的进程间快速
切换来实现的。
这种并发形式允许多个用户同时与系统交互。
多核处理器是将多个CPU(称为“核”)集成到一个集成电路芯片上。
图1-7描述的是一个典型多核处理器的组织结构,其中微处理器芯片有4个CPU核,每个核都有
自己的L1和L2高速缓存,其中的L1高速缓存分为两个部分——一个保存最近取到的指令,另一个存
放数据。
超线程,有时称为同时多线程(simultaneous multi-threading),是一项允许一个CPU执行多个
控制流的技术。
- 指令级并行
在较低的抽象层次上,现代处理器可以同时指向多条指令的属性称为指令级并行。
如果处理器可以达到比一个周期一条指令更快的执行效率,就称之为超标量(super-scalar)处理器。
- 单指令、多数据并行
在最低层次上,许多现代处理器拥有特殊的硬件,允许一条指令产生多个可以并行执行的操作,
这种方式称为单指令、多数据,即SIMD并行。
1.9.3 计算机系统中抽象的重要性
计算机系统中使用的几个抽象,如图1-18所示。
在学习操作系统时,我们介绍了三个抽象:文件是对I/O设备的抽象,虚拟内存是对程序存储器的抽象,
而进程是对一个正在运行的程序的抽象。我们可以在增加一个新的抽象:虚拟机,它提供对整个计算机的抽
象,包括操作系统、处理器和程序。
1.10 小结
操作系统内核是应用程序和硬件之间的媒介。
它提供三个基本的抽象:
1)文件是对I/O设备的抽象;
2)虚拟内存是对主存和磁盘的抽象;
3)进程是处理器、主存和I/O设备的抽象。
网络提供了计算机系统之间通信的手段。从特殊系统的角度来看,网络就是一种I/O设备。