- 信息就是位+ 上下文
hello 程序的生命周期是从一个源程序开始的,即程序员通过编辑器创建并保存的文本文件,文件名是 hello.c。源程序实际上就是一个由0和1组成的位序列,8个位被组织成一组,称为字节。每个字节表示程序中的某些文本字符。
美国国家标准学会(ANSI)在1989年颁布了 ANSI C的标准,后来C 语言的标准化成了C 语言和一些列函数库,即所谓的C 标准库。
-
- C 语言与Unix 操作系统关系密切。
- C 语言小而简单
- C 语言是为实践目的设计的。
- 程序被其他程序翻译成不同的格式
hello 程序的声明周期是从一个高级C 语言程序开始的,因为这种形式能够被人读懂。而且,为了在系统上运行hello.c 程序,每条C 语句都不许被其他程序转化为一些列的低级机器语言指令。然后这些指令按照一种称为可执行目标程序的格式打好包,并以二进制磁盘文件的形式存放起来。目标程序也称为可执行目标文件。
hello.c (源程序文本)—>预处理器(cpp)—> hello.i(修改了源程序文本);
hello.i —> 编译器(ccl)—> hello.s(汇编程序文本);
hello.s—> 汇编器(as)—> hello.o(可重定位目标程序二进制);
printf.o、hello.o —> 链接器(ld)—> 可执行目标程序二进制。
-
- 预处理阶段
预处理器根据以字符开头的命令,修改原始的C 程序。
-
- 编译阶段
编译器将文本文件hello.i翻译成文本文件hello.s。
-
- 汇编阶段
汇编器将hello.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序(relocatable object program)的格式,并将结果保存在目标文件hello.o中。
-
- 链接阶段
连接器负责将汇编生产的文件合并到hello.o文件,他是一个可执行目标文件,可以被加载到内存中,由系统执行。
GCC 是 GNU项目开发出来的众多有用工具之一。GNU项目是一个免税的慈善项目 。该项目的目标非常宏大,就是开发一个完成的类Unix的系统,其源嗲吗能够不受限制地被修改和传播。GNU 项目已经开发除了一个包含Unix操作系统的所有主要部件的环境,但内核除外,内核由Linux项目独立发展而来的。GNU 环境包括 EMACS 编辑器、GCC编译器、GDB调试器、汇编器、链接器、处理二进制文件的工具以及其他一些部件。GCC编译器已经发展到支持许多不同的语言,能够为不同的机器生产代码。支持的语言包括C、C++、Fortran、Java、Pascal、Object-C和Ada。
3.了解编译系统如何工作是大有益处的
对于像hello.c这样简单的层序,我们可以依靠编译系统生成正确有效的机器代码。但是有一些重要的原因促使程序员必须知道编译系统是如何工作的。
- 优化程序性能
- 理解链接时出现的错误
- 避免安全漏洞
4.处理器读并解释存储在内存重的指令
shell 是一个命令解释器,它输出一个提示符,等待输出一个命令,然后执行这个命令。如果该命里该行的第一个单词不是一个内置的shell 命令,那么shell就会假设这是一个可执行文件的名字,它将加载并运行这个文件。
4.1.系统的硬件组成
- 总线:贯穿这个系统的是一组电子管道,称作总线,它携带信息字节并负责在各个部件间传递。通常总线被设计成传送定长的字节块,也就是字(word)。
- I/IO 设备:I/O 设备是系统与外部世界的联系通道。
- 主存:主存是一个临时存储设备,在处理器执行程序时,用来存放程序和程序处理的数据。
- 处理器:中央处理单元,简称处理器,是解释、执行存储主存中指令的引擎。处理器的核心是一个大小为一个字的存储设备,称为程序计数器(PC)。在任何时刻,PC 都指向主存中的某条机器语言指令(即含有该条指令的地址)。
- 加载:从主存复制一个字节或者一个字到寄存器,以覆盖寄存器原来的内容
- 存储:从寄存器复制一个字节或者一个字到主存的某个位置,以覆盖这个位置上原来的内容。
- 操作:把两个寄存器的内容复制到ALU,ALU对这两个字做算数运算,并将结果存放到一个寄存器中,以覆盖该寄存器中原来的内容。
- 跳转:从指令本身中抽取一个字,并将这个字复制到程序计数器(PC)中,以覆盖PC 中原来的值。
5.高速缓存至关重要
针对处理器与主存之间的差异,系统设计者采用了更小更快的存储设备,称为高速缓存存储器,作为暂时的集结区域,存放处理器近期可能会需要的信息。
6.存储设备形成层次结构
在处理器和一个比较慢的设备之间掺入一个更小更快的存储设备的想法已经成为一个普通的观念。存储器层次结构的主要思想是上一层的存储器作为低一层存储器的高速缓存。
7.操作系统管理硬件
所有应用程序对硬件的操作尝试都必须通过操作系统。操作系统有两个基本功能:(1)防止硬件被失控的应用程序滥用;(2)向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。操作系统通过几个基本的抽象概念(进程、虚拟内存和文件)来实现这两个功能。
7.1进程
进程是操作系统对一个正在运行的程序的一种抽象。在一个系统上可以同时运行多个进程,而每个进程都好像在独占地使用硬件。而并发运行,则是说一个进程的指令和另一个进程的指令是交错执行的。在大多数系统中,需要运行的进程数是多余可以运行他们的CPU个数的。无论是在单核还是多核系统中,一个CPU看上去都像是在并发地执行多个进程,这是通过处理器在进程间切换实现的。操作系统实现这种交错执行的机制为上下文切换。
操作系统保持跟踪进程运行所需的所有状态信息。这种状态,也就是上下文,包括许多信息,比如PC 和寄存器文件的当前值,以及主存的内容。在任何一个时刻,单处理器系统都只能执行一个进程的代码。当操作系统决定要把控制权从当前进程转移到某个新进程时,就会进行上下文切换,即保存当前进程的上下文、恢复新进程的上下文,然后将控制权传递到新进程。新进程就会从它上次停止的地方开始。
7.2线程
尽管通常我们认为一个进程只有单一的控制流,但在现代系统中,一个进程实际上可以由多个称为线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。由于网络服务器中对并行处理的需求,线程称为越来越重要的编程模型,因为多线程之间比多进程之间更容易共享数据,也因为线程一般来说都比进程更高效。
7.3虚拟内存
虚拟内存是一个抽象概念,它为每个进程提供了一个假象,即每个进程都在独占地使用9哦那个主存。每个进程看到的内存都是一致的,称为虚拟地址空间。
进程的虚拟地址空间
内核虚拟内存 - 用户代码不可见内存
用户栈(运行时创建的)
共享库的内存映射区域 - printf函数
运行时堆(在运行时由malloc创建的)
读/写数据
只读代码和数据 - 从hello可执行文件加载进来的
程序开始
- 程序代码和数据
- 堆
- 共享库
- 栈
- 内核虚拟内存
7.4文件
文件就是字节序列,仅此而已。
8.系统之间利用网络通信
现代系统通常通过网络和其他系统连接到一起。从一个单独的系统来看,网络可视为一个I/O设备。
9.重要主题
系统不仅仅只是硬件。系统是硬件和系统软件互相交织的集合体,他们必须共同协作以达到运行应用程序的最终目的。
9.1Amdahl 定律
对提升系统某一部分性能所带来的效果做出了简单却有见地的观察。该定律的主要思想是,当我们对系统的某个部分加速时,其对系统整体性能的影响取决于该部分所需执行时间与该时间的比例 a ,而该部分性能提升比例为 k 。即该部分初始化所需时间为 aT(old)。计算加速比为:S = 1/((1-a)+a/k)这就是Amdahl 定律的主要观点—想要显著加速整个系统,必须提升全系统中相当大的部分的速度。
9.2并发和并行
并发是一个通用的概念,指一个同时具有多个活动的系统;而并行指的是 用并发来使一个系统运行的更快。并行可以在计算机系统的多个抽象层次上运行。
- 线程级并发
构建在进程这个抽象之上,我们能够设计出同时有多个程序执行的系统。这就导致了并发。使用线程,我们甚至能够在一个进程中执行多个控制流。传统意义上,这种并发执行只是模拟出来的,是通过一台计算机在它正在执行的进程快速切换实现的。。这种并发形式允许多个用户同时与系统交互。在以前,即使处理器必须在多个任务间切换,大多数实际的计算也都是由一个处理器来完成的。这种配置称为单处理器系统。
超线程,有时称为同时多线程,是一项允许一个CPU 执行多个控制流的技术。
多线程的使用可以从两方面提高系统性能。首先,它减少了在执行多个任务时模拟并发的需求。其次,它可以使应用程序运行得更快,当然,这必须要求程序是以多线程方式来书写的,这些线程可以并行地高效执行。
- 指令集并行
在较低的抽象层次上,现代处理器可以同时执行多条指令的属性称为指令级并行。
如果处理器可以达到比一个周期一条指令更快的执行苏鲁,就称之为超标量处理器。
- 单指令、多数据并行
在最低层次是那个,许多现代处理器拥有特殊的硬件,允许一条指令产生多个可以执行的操作,这种方式称为单指令、多数据,即SIMD 并行。
9.3计算机系统中抽象的重要性
抽象的使用是计算机科学中最为重要的概念之一。
文件是对I/O 设备的抽象,虚拟内存是对程序存储器的抽象,而进程是对一个正在运行的程序的抽象。虚拟机提供对整个计算机的抽象,包括操作系统、处理器和程序。
10.小结
计算机系统是由硬件和系统软件组成的,他们共同协作以运行应用程序。
处理器读取并解释存放在主存里的二进制指令。
操作系统内核是应用程序和硬件之间的媒介。它提供了基本的抽象。
网络提供了计算机系统之间通信的手段。