第一章从程序员角度讲解计算机运行和通信
第一部分描述 计算机的程序结构 硬件视角
第二部分讲解计算机程序运行 软件视角-单个计算机的运行
第三部分 讲解程序间的交互和通信 软件视角-计算机之间的通信
本篇描述 计算机系统漫游
目录如下:
第1章:计算机系统漫游
第一部分:程序结构和执行
第2章:信息的表示和处理
第3章:程序的机器级表示
第4章:处理器体系结构
第5章:优化程序性能
第6章:存储器层次结构
第二部分:在系统上运行程序
第7章:链接
第8章:异常控制流
第9章:虚拟存储器
第三部分:程序间的交互和通信
第10章:系统级I/O
第11章:网络编程
第12章:并发编程
===第一章:计算机系统漫游==================================================
计算机系统的实现方式虽然不同,但是所有计算机系统都有相似的硬件和软件组件;了解编译器如何实现过程调用的;
编写自己的unix外壳,自己的动态存储分配宝,自己的web服务器;认识到并发带来的希望和陷阱。
通过跟踪hello程序的生命周期开始对系统的学习---从它被程序员创建,到在系统上运行,输出简单的消息,然后终止。
------------code/hello.c------------------------------
#include<stdio.h>
int main(){
printf("hello world ");
}
--------------code/hello.c----------------------------
- 1.1 信息就是位+上下文
hello.c文件由ASCII字符构成的文件称为文本文件,其他文件都是二进制文件。
hello.c程序的生命周期从一个源程序或者源文件开始的,源程序是由值0和1组成的位序列,
8个位=一个字节=一个文本字符(大部分现代系统都使用ASCII标准表示文本字符)=一个单字节大小的整数值
系统的所有信息-包括磁盘文件、存储器中的程序、数据 网络上传送的数据,都是一串位表示的,区分不同数据对象的唯一方法是
我们读到这些数据对象时的上下文。同一个字节序列,在不同的上下文中表示的可能是一个整数、浮点数。字符串或者机器指令。
- 1.2 程序被其他程序翻译成不同的格式
为了在系统上运行hello.c程序,每条c语句都必须被其他程序转化为一系列的低级机器语言指令,这些指令按照一种可称为可执行目标程序的格式打好包,并以二进制磁盘文件的形式存放起来。目标程序称为-可执行目标文件。
在unix系统上,从源文件到目标文件的转化是由编译器驱动程序完成的:
unix>gcc -o hello hello.c
在这里,gcc编译器驱动程序读取源文件hello.c,并把它翻译成可执行目标文件hello,这个过程共分为四个阶段:
hello.c(源程序文本)
--预处理(cpp)(处理#开始的命令,修改原始的c程序)=hello.i(被修改的源程序 文本)
--编译器(cll)=hello.s(汇编程序 文本)(汇编程序)
--汇编器(as)(把汇编程序翻译成机器指令,打包成可重定位目标程序)=hello.o(可重定位目标程序 二进制)+printf.o
--链接器(ld)=hello(可执行目标二进制)(可执行文件:可以被加载到内存中,由系统执行)
一起构成了编译系统
- 1.3 了解编译系统如何工作
好处:
1)优化程序性能
switch是否比if-then-else高效?
一个函数调用的开销多大?
while比for更高效吗?
指针引用比数组索引更有效率吗?
为什么简单重新排列一下一个算数表达式中的括号就能让一个函数运行得更快?
编译器如何把不同的C语言结构转换成它们的机器语言的。
如何通过简单转换c语言代码,以帮助编译器更好地完成工作,从而调整C程序的性能。
存储器系统的层次结构特性,C语言编译器将数组存放在存储器中的方式,C程序又是如何能够利用这些知识从而更高效运行。
2)理解链接时出现的错误
程序错误往往与连接器操作有关,链接器报告无法解析的引用,是啥意思?静态变量和全局变量的区别?不同C文件定义了名字相同的两个全局变量会发生什么?
静态库和动态库的区别?在命令行上排列库的的顺序有什么影响?为什么有些链接错误知道运行时才会出现?解答见第7章
3)避免安全漏洞
缓冲区溢出是很多网络和服务器安全漏洞的原因,需要限制从不受信任的站点接收数据的数量和格式。
学习编程的第一步就是,理解数据和控制信息从哪出在程序栈上的方式引起的后果,学习堆栈原理和缓冲区溢出错误。
- 1.4 处理器读并解释存储在存储器中的指令
hello这个可执行文件在磁盘上,要想在unix系统上运行该可执行文件,把文件名输入到shell应用程序中,外壳(shell)是一个命令行解释器,它输出一个提示符,等待输入一个命令行,如果这个命令行不是一个内置的外壳命令,那么外壳就会假设这是一个可执行文件的名字,它就会加载并运行这个文件。所以外壳将运行hello程序。然后等待程序终止,终止后,外壳随后输出一个提示符,等待下一个输入的命令行。
- 1.4.1 系统的硬件组成
典型的系统硬件组织如下:
cpu:中央处理单元(ALU:算数、逻辑单元 ,pc:程序计数器) usb:通用串行总线
1)总线
贯穿整个系统的一组电子管道,携带信息字节并在各个部件之间传递,传送定长的字节块i(即字长word),字节数即字长,是一个基本的系统参数,4个字长即32位,8个是64位。
2)I/O设备
系统与外部世界的联系通道。比如:键盘 鼠标 作为用户输入,显示器作为用户输出,磁盘 用于长期存储数据和程序。每一个Io设备都通过适配器(封装方式:一块插在主板插槽上的卡)或者控制器(封装方式:置于IO设备本身或者系统的主印制电路板的芯片组),适配器和控制器都是为了在IO总线和设备之间传递信息。在应用程序中利用IO接口访问网络类设备。、
3)主存 是指一个临时存储设备,在处理器执行程序时,用来存放程序和数据,物理上看是DRAM-动态随机存取存储器芯片,逻辑上是一个线性的字节数组,每个字节都有其对应的地址即数组索引,这些地址从0开始,组成程序的每条机器指令都由不同数量的字节构成。
4)处理器
指令集结构的简单实现,指令集结构描述每条机器指令代码的效果,指令集结构提供了对实际处理器硬件的抽象。执行主存中的指令,其核心是PC-程序计数器,这事一个字长的寄存器,任何时刻pc都指向主存中的一条机器语言指令--即含有该条指令的地址,处理器一直在执行pc指向的指令,更新pc指向下一条指令,指令执行模型由指令集结构决定。
处理器从pc指向的存储器读取指令,解释指令中的位,执行指令指示的简单操作,然后更新pc,使其指向下一条指令。
操作主要是围绕着主存,寄存器文件和ALU进行,cpu在指令的要求下可以执行以下操作:
加载;把一个字节或者字从主存复制到寄存器,覆盖原来寄存器的内容
存储:把一个字节或者字,从寄存器复制到主存,覆盖这个位置原来的内容
操作:把两个寄存器的内容复制到ALU,ALU对这两个字做算术操作,并把结果放到一个寄存器中,覆盖原来内容
跳转:从指令中抽取一个字,把这个字复制到pc中
处理器只是这些指令集结构的简单实现,但是使用了非常复杂的加速机制来加速程序的执行。
- 1.4.2 运行hello程序
一旦目标文件hello中的代码和数据被加载到主存,处理器就开始执行hello程序的main程序中个机器语言指令。
- 1.5 高速缓存至关重要
- 1.6 存储设备形成层次结构
一个存储器的层次结构示例:
可以用不同高速缓存的知识来提高程序性能,同理,程序员可以利用对整个存储器层次结构的理解来提高程序性能。
存储器层次结构的主要思想是一层上的存储器作为低一层存储器的高速缓存,因此主存是磁盘的高速缓存,再某些分布式文件系统的网络系统中,本地磁盘就是存储在其他系统中磁盘的数据高速缓存。
- 1.7 操作系统管理硬件
hello程序依靠操作系统提供的服务,访问键盘 显示器 磁盘 主存,输出信息,即操作系统是应用程序和硬件之间的一层软件,所有应用程序对硬件的操作都必须经过操作系统。,
操作系统通过几个基本的抽闲个概念来实现管理硬件,文件,虚拟存储器,进程,文件是对IO设备的抽象,虚拟存储器是对主存和磁盘IO设备的抽象表示,进程则是对处理器 主存 io设备的抽象
- 1.7.1 进程
进程是操作系统对正在运行的程序的一种抽象。操作系统实现交错执行的机制称为上下文切换。操作系统保持跟中该进程运行所需的所有状态信息,这种该状态就是上下文,包括很多信息:pc和寄存器文件的当前值,贮存的内容,在任何一个时刻,单处理器系统都只能执行一个进程的代码,当错做系统把控制权从当前进程转移到新锦成时候,就会进行上下文切换,即保存当前进程的上下文,回阜新进程的上下文,然后把控制权传递到新进程,新进程就会从上次停止的地方开始。
- 1.7.2 线程
多线程比多进程更容易共享数据。
- 1.7.3 虚拟存储器
虚拟存储器为每个进程提供了抽象,即每个进程都在独占地使用主存,每个进程看到的是一致的存储器,称为虚拟地址空间,地址空间最上面的区域是为操作系统中的代码和数据保留的,这对所有进程都一样,地址空间的底部区域存放用户进程定义的代码和数据。
进程的虚拟地址空间由大量准确定义的区构成,每个区都有专门的功能。
程序代码和数据:一开始运行时就被规定了大小
共享库:
堆:运行时确定
栈:位于用户虚拟地址空间的顶部,便一起用它来实现函数调用
内核虚拟存储器:内核总是驻留在内存中,是操作系统的一部分,不允许应用程序读写这个区域的内容,或者调用内核代码定义的函数。
虚拟存储器的运作需要硬件和操作系统软件之间精密复杂的交互,包括对处理器生成的每个地址的硬件翻译,其基本思想是把一个进程虚拟存储器的内容存储在磁盘上,然后用主存作为磁盘的高速缓存。
- 1.7.4 文件
文件就是字节序列,每个io设备都可以视为文件,包括 磁盘 键盘 显示器 网络,系统中所有的输入输出都是通过一小组称为unix IO的系统函数调用读写文件实现的。
它向应用程序提供了一个视角,来处理所有各式各样的io设备,比如处理磁盘文件内容的程序员不需要了解具体的磁盘技术,同一个程序可以在使用不同磁盘技术的不同系统上运行。
- 1.8 系统之间利用网络通信
系统并不是孤立的硬件和软件的集合。
从一个单独的系统来看,网络课一视为一个io设备,当系统从主存,把字节复制到网络适配器时,数据流经网络到达另外一台机器,系统可以读取从其他机器发送来的数据,并把数据复制到自己的主存。
- 1.9 重要主题
1)并发和并行
2)抽象
文件是对IO的抽象,虚拟存储器是对程序存储器的抽象,进程是对正在运行的程序的抽象,虚拟机是对整个计算机的抽象。
- 1.10 小结
计算机内部的信息被表示为一组组的位,他们根据上下文有不同的解释方式,程序被其他程序翻译成不同的形式,开始是ASCII文本,然后被编译器和链接器翻译成二进制文本。
处理器读取并解释存放在主存里的二进制指令。犹豫计算机吧大量的时间用于存储器 IO设备和cPU寄存器之间的复制数据,所以把系统中的存储设备划分成层次结构,高层存储设备是底层存储设备的缓存。
操作系统内核是用用程序和硬件之间的媒介,提供三个基本的抽象:文件是对IO设备的抽象,虚拟存储器是对内存和磁盘的抽象,进程是对处理器 主存 IO设备的抽象。
网络提供了计算机系统之间通信的手段。从系统角度看,网络就是一种IO设备。
=======我的感悟=====================================================
硬件角度看计算机系统:处理器即cpu+主线+内存+IO设备 (经过操作系统这个中介的翻译)VS 应用程序视角:处理器+内存+磁盘=进程 IO设备=文件 虚拟存储器=磁盘+主存
操作系统提供了软件和硬件之间的抽象:
指令集结构提供了对实际处理器硬件的抽象,操作系统负责指令的硬件翻译。
进程是以应用程序的视角看到的计算机,是操作系统提供给应用程序的计算机的样子。
操作系统要做的是把虚拟存储器的内容存储在磁盘上,然后用主存作为磁盘的高速缓存。
程序的视角看计算机就是进程,具体进程之下硬件是如何执行的,看操作系统。
所谓的计算机执行只有cpu指令集的执行(加载,存储,操作(ALU),跳转),其余都是copy操作。所谓网络通信就是计算机之间的copy,作用等同于本地的复制黏贴,真正的计算只有少量一点。