深入理解计算机系统01-计算机系统漫游

第一章:计算机系统漫游

1.1 信息就是位+上下文

#include <stdio.h>

int main()
{
    printf("hello, world\n");
    return 0;
}

// hello.c

  hello程序的生命周期从源程序(源文件)hello.c开始,这是一个程序员创建并保存的文本文件。源程序实际上也是一个由0和1组成的位(bit,比特)序列,8个bit组织成一组称为字节(byte)。每个字节表示源程序中的文本字符。大部分现代计算机使用ASCII标准来表示文本字符,即用单个字节的整数值来表示一个字符,图1-2就是hello.c的ASCII码表示:

   hello.c是以字节序列的方式存储在文件中的,每一个字节都有一个整数值,对应ASCII字符。像hello.c这种只有ASCII字符构成的文件称为文本文件,所有其他文件都称为二进制文件。

  hello.c的表示方法说明了:系统中所有信息——包括磁盘文件、内存中的程序、内存存放的用户数据、网络上传送的数据等都是一串比特;区分不同数据对象的唯一方法是我们读取这些数据对象时的上下文,在不同的上下文中一个同样的字节序列可能表示一个整数、浮点数、字符串或机器指令

  数字的机器表示方式与实际的整数和实数是不同的,它们是对真值有限近似值。

1.2 程序被其他程序翻译成不同格式

  hello程序是从一个高级C语言程序开始的,为了在系统上运行hello.c程序,必须将C语句级语言)都转化为一些列低级的机器语言指令。然后将这些指令按照一种称为可执行目标程序的格式打包,并以二进制磁盘文件的形式存储起来(即可执行目标文件)。目标程序也称为可执行目标文件。

  从源程序(源文件)到目标程序(目标文件)的转化一般是由编译器驱动程序来完成的:

linux> gcc -o hello hello.c

  GCC编译器驱动程序读取源文件hello.c并翻译成目标文件hello的过程,分四个阶段完成。执行这四个阶段的程序(预处理器、编译器、汇编器、链接器)一起构成了编译系统(compilation system):

 

 

  •  预处理阶段:预处理器根据以#字符开头的命令(预处理指令)修改原始C程序生成修改后的C程序。比如hello.c中的#include<stdio.h>指令就是告诉预处理器读取系统头文件stdio.h内容并将其直接插入到程序文本中得到另一个C程序hello.i(还是文本文件)。
  • 编译阶段:编译器将文本文件hello.i翻译成文本文件hello.s(这是一个汇编语言程序,里面就是由C语言程序代码翻译得到的汇编语言代码),该程序中包含的main函数定义如下:
1 main:
2     subq $8, %rsp
3     movl $.LC0, %edi
4     call puts
5     movl $0, %eax
6     addq $8, %rsp
7     ret

    main函数定义中2~7行的的每条语句(汇编代码)以文本格式描述了一条低级机器语言指令(汇编语言本质就是机器语言指令的助记符)。汇编语言是非常有用的,它为不同的高级语言的不同编译器提供了通用的输出语言

  • 汇编阶段:汇编器将hello.s翻译成机器语言指令,并把这些指令打包成一种叫做可重定位目标程序(relocatable object program)的格式保存在目标文件hello.o中。hello.o是二进制文件里面包含了main函数的指令编码,如果用文本编辑器打开hello.o将看到一堆乱码(上下文不是文本,里面的字节序列并不表示字符,强行解释成字符所以乱码)。
  • 链接阶段:hello程序调用了标准C库的printf函数(由C编译器提供),printf函数存在于名为printf.o的预编译好了的目标文件中。链接器就负责将这个文件合并到hello.o程序中,结果就得到了hello这个可执行目标文件(简称:可执行文件),可以被加载到内存中,由系统执行。

1.3 了解编译系统如何工作大有益处

 

 1.4 处理器读取并解释存储在内存中的指令

  在Unix系统上运行可执行文件,将其文件名输入到shell程序中。shell是一个命令行解释器(也叫系统外壳程序),它输出一个提示符等待用户输入命令行,然后执行这个命令。如果命令行的第一个单词不是内置shell命令,它就假设这是一个可执行文件的名字,它将加载并运行这个文件

linux> ./hello
hello, world
linux>

1.4.1 系统的硬件组成

 

   1.总线

  贯穿整个系统的是一组电子管道,称作总线,它携带信息字节并负责在各个部件间传递。通常总线被设计成传送定长的字节块,也就是字(word),word的字节数(即字长,也叫机器字长)是一个基本的系统参数。现在的大多数机器字长要么是4字节(32位)要么是8字节(64位)。

  2.I/O设备

  I/O(输入/输出)设备是系统与外界联系的通道。如:作为用户输入的键盘和鼠标、作为输出的显示器、用于存储数据和程序的磁盘驱动器。每个I/O设备都通过一个控制器或适配器与I/O总线相连。控制器和适配器的区别主要在于它们的封装方式,控制器是I/O设备本身或者是系统的主印刷电路板(通常称作主板)上的芯片组,而适配器则是一块插在主板插槽上的卡,无论如何它们的功能都是在I/O总线和I/O设备之间传递信息

  3.主存

  主存是一个临时存储设备在处理器执行程序时用来存储程序和程序处理的数据。从物理上来说,主存是由一组动态随机存取存储器(DRAM)芯片组成;从逻辑上来说,存储器是一个线性的字节数组,每一个字节有其唯一的地址(数组索引),这些地址是从0开始的。一般来说,组成程序的每条机器指令都是由不同数量的字节构成。C程序变量的大小是根据数据类型变化的,如Linux x86-64机器上short类型数据需要2字节,int和float需要4字节,long和double需要8字节。

  4.处理器

  中央处理单元(CPU)简称处理器,是解释(执行)存储在主存中指令的引擎。处理器的核心是一个大小为一个word的存储设备(或寄存器)称为程序计数器(PC:Program Counter)。在任何时刻PC都指向主存中的某条机器指令(即PC中包含了下一条执行的机器指令的地址)

  从系统通电到断电,处理器一直在不断的执行PC指向的指令,再更新PC,使其指向下一条指令(即CPU一直在“取指执行”)。CPU的指令执行模型由指令集架构决定,在这个模型中,指令按照严格的顺序执行,而执行一条指令包含执行一系列步骤。CPU从PC指向的内存读取指令,解释指令中的位并执行指令指示的操作,然后更新PC指向下一条指令,下一条指令在内存中的位置并不一定和刚刚执行的指令相邻。

  寄存器文件是一个小型存储设备,由一些单个字长的寄存器组成,每一个寄存器都有唯一的名字。算术逻辑单元(ALU)计算新的数据和地址值。

 

 

 1.4.2 运行hello程序

 

 

 

 

 

 

 1.5 高速缓存至关重要

 

 

 1.6 存储设备层次结构

 

 1.7 操作系统管理硬件

  运用程序并不能直接访问硬件(鼠标、键盘、显示器、主存等),它们依靠操作系统提供的服务。可以把操作系统看成是运用程序和硬件之间的一层软件,运用程序所有访问硬件的操作都必须通过操作系统。

 

   操作系统有2个基本功能:(1)防止硬件被失控的软件滥用(2)向运用程序提供简单一致的机制(即接口)来来控制复杂且不同的硬件。操作系统通过几个基本的抽象概念(进程、虚拟内存、文件)来实现这2个功能。文件时对I/O设备的抽象,虚拟内存时对主存和磁盘I/O设备的抽象,进程则是对处理器、主存和I/O设备的抽象表示。

 

 1.7.1 进程

 

 

 

 

 

 1.7.2 线程

 

 1.7.3 虚拟内存

  虚拟内存时一个抽象概念,它为每一个进程提供了一个假象即每个进程都独占主存。每个进程看到的内存内存都是一致的,称为虚拟地址空间

 

   

 

 1.7.4 文件

  文件就是字节序列,每一个I/O设备(包括磁盘、键盘、显示器、网络等)都可以看成是文件。(Linux一切皆文件思想)

1.8 系统之间利用网络通信

 

 

 

 1.9 重要主题

  计算机系统是由硬件和系统软件共同组成,它们必须共同协作才能运行运用程序。

1.9.1 Amdahl定律

  

 

 1.9.2 并发与并行

 

 

 1.10 小结

 

 

posted @ 2021-09-21 17:06  碎银三二两  阅读(145)  评论(0编辑  收藏  举报