Chapter1 计算机系统漫游

Chapter1 计算机系统漫游

计算机系统是由硬件和系统软件组成的,它们共同工作来运行程序。

1.1 信息就是位加上下文

hello程序的生命周期从一个源程序开始,文件名为hello.c。源程序实际上是由值0和1组成的位,8个位(比特)称为一个字节,每个字节表示程序中的某些文本字符。

大部分现代计算机系统都是用ASCII标准来表示文本字符(用唯一的单字节大小的整数值来表示每个字符)

在这里插入图片描述

hello.c这样由ASCII字符构成的文件成为文本文件,其他文件都称为二进制文件。

基本思想:系统中的所有信息——包括磁盘文件、内存中程序、内存中存放的用户数据、网络中传送的数据,都是由一串比特表示的。区分不同数据对象(整数、浮点数、字符串、机器指令)的唯一方法是我们读到这些数据对象时上下文。数字的机器表示方式,与实际的整数和实数是不同的,是对真值的近似。

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

为了在系统中运行hello.c程序,每条C语句都必须被编译驱动程序转化为一系列机器语言指令,然后被打包为可执行目标程序,又称可执行目标文件,以二进制磁盘文件的形式存放。

linux> gcc -o hello hello.c

编译系统:预处理器、编译器、汇编器、链接器

编译过程如下:

在这里插入图片描述

  • 预处理阶段。预处理器(cpp)根据以#开头的命令,读取头文件内容,插入到原始C程序中,得到以.i为文件拓展名的程序。
  • 编译阶段。编译器(ccl)将hello.i翻译成汇编程序hello.s。
  • 汇编阶段。汇编器(as)将hello.s翻译成机器语言指令,并把这些指令打包为可重定位目标程序hello.o。
  • 链接阶段。编译器提供的标准C库中的函数,存在于单独预编译好的目标文件中(.o),链接器(ld)负责将该文件和hello.o文件合并,得到可执行目标文件hello。

1.3 了解编译系统如何工作的益处:

  1. 优化程序性能
  2. 理解链接时出现的错误
  3. 避免安全漏洞

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

linux> ./hello

1.4.1 系统的硬件组成

在这里插入图片描述

  • 总线:携带信息字节并负责在各个部件中传递。传送定长的字节块,字。字中的字节数称为字长,是一个基本的系统参数。
  • I/O设备:系统与外部世界联系的通道:
    1. 作为用户输入的键盘和鼠标;
    2. 作为用户输出的显示器;
    3. 长期存储数据和程序的磁盘。
      每一个I/O设备都哦通过一个控制器或者适配器和I/O总线相连。
      两者的区别在于封装方式。控制器是I/O设备本身或者系统主板上的芯片组;适配器则是主板插槽上的一块卡。
  • 主存:临时存储设备。
    • 物理上来讲,主存由一组动态随机存取器(DRAM)芯片组成。
    • 逻辑上来讲,存储器是一个线性的字节数组,每个字节都有唯一的从零开始的地址。一般而言,每条不同的机器指令由不同数量的字节构成,与C程序变量相对于的数据项大小根据类型变化。
  • 处理器(CPU,中央处理器):解释存储在内存中指令的引擎。
    处理器的核心是PC(程序计数器),任何时刻均指向主存中某条机器语言指令。从系统通电开始,直到断电,CPU不断执行PC指向的指令,再更新PC使其指向下一条指令。这个模型由指令集架构决定。
    指令集架构:指令按照严格的顺序执行,而执行一条指令又包含一系列步骤。CPU从PC指向的内存中读取指令,解释指令中的位,执行该指令指示的操作,然后更新PC,使其指向下一条指令,这条指令不一定和上一条指令相邻。
    上述操作围绕主存、寄存器文件和ALU进行。
    寄存器文件由一些单个字长的寄存器组成,ALU计算新的数据和地址值。
    1. 加载:从主存中复制一个字节或者一个字到寄存器;
    2. 存储:从寄存器复制一个字节或者一个字到主存;
    3. 操作:把寄存器内容复制到ALU,ALU对值做算数运算,并将结果放在一个寄存器中;
    4. 跳转:从指令本身中抽取一个字,并将这个字复制到PC中。

    处理器看上去是指令集架构的简单实现,实际上使用了非常复杂的机制来加速程序的运行。指令集架构描述每条机器代码指令的效果,微体系结构描述处理器如何实现。

1.4.2 运行程序

  1. 从键盘上读取hello命令
    在这里插入图片描述

  2. 从磁盘加载可执行文件到主存
    在这里插入图片描述

  3. 将输出字符从存储器写到显示器
    在这里插入图片描述

1.5 高速缓存至关重要

程序的机器指令最初放在磁盘上,当程序加载时,被复制到主存。当处理器运行程序时,指令又被复制到处理器。

一个典型的寄存器文件读取速度比从主存中读取要快几乎100倍。而且随着半导体技术的进步,这种处理器与主存之间的差距还在持续增大。加快处理器的运行速度比加快主存的运行速度要便宜得多。

针对处理器与主存之间的差异,系统设计者采用了高速缓存存储器(cache),作为暂时存放区域,存放CPU近期可能需要的信息(局部性原理)

高速缓存可以将程序的性能提高一个数量级。

高速缓存的局部性原理,即程序具有访问局部区域里代码和数据的趋势。

1.6存储设备形成层次结构

在这个层次结构中,从上到下,设备的访问速度越来越慢,容量越来越大,每个字节的造价也越来越便宜。

寄存器文件位于最顶层;高速缓存位于后三层。其中L1位于CPU芯片上,读取速度几乎和寄存器文件一样,L2通过一条特殊的总线和CPU相连,访问速度为L1的$1/5 $

在这里插入图片描述

主要思想:上一层的存储器作为低一层次的存储器的高速缓存。

1.7 操作系统管理

在这里插入图片描述
在这里插入图片描述

当shell加载hello程序,以及hello程序运行时,shell和hello程序都没有直接访问I/O设备和主存,取而代之的是,它们依靠操作系统提供的服务。

操作系统的基本功能:

  • 防止硬件被失控的应用程序滥用;
  • 向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。
    1. 文件是对I/O设备的抽象;
    2. 虚拟内存是对主存和I/O设备的抽象;
    3. 进程是对CPU、主存和I/O设备的抽象。

1.7.1 进程

进程是对操作系统正在运行的一个程序的抽象。在一个系统上可以运行多个进程,而每个进程看起来好像独占地使用硬件。

实际上,传统单核系统确实一个时刻只能执行一个进程,而多核系统能够同时执行多个进程。

但是,无论是单核系统还是多核系统,一个CPU看上去都像是并发执行多个进程,这是通过CPU在进程间切换来实现的。

进程的并发运行,指一个进程的指令和另一个进程的指令是交错执行的。

操作系统保持跟踪进程运行所需的所有状态信息,称为上下文。任何一个时刻,单处理器都只能执行一个进程的代码。当操作系统决定要将控制权从当前进程转移到新进程时,就会进行上下文切换,即保存当前进程上下文,恢复新进程上下文,然后将控制权递交给新进程,新进程就会从上次停止的地方开始运行。

在这里插入图片描述

进程间的转换是由操作系统kernel(内核)管理的。当应用程序需要操作系统某些操作时,他就执行一条特殊的系统调用指令。内核不是一个独立的进程,相反,他是系统管理全部进程所用代码和数据结构的合集。

1.7.2 线程

一个进程实际上可以由多个称为线程的执行单元构成,每个线程都运行在进程的上下文中,共享同样的代码和全局数据。

多线程比多进程之间更容易共享数据。

1.7.3 虚拟内存

虚拟内存是一个抽象概念,为每一个进程提供了一个假象,即每个进程都在独占地使用主存。

每个进程看到的内存都是一致的,称为虚拟地址空间。

在这里插入图片描述

  • 内核虚拟内存:
    不允许程序读写这个区域或者直接调用内核代码定义的函数。

  • 程序代码和数据:
    对所有进程来说,代码是从同一固定地址开始的,紧接着是和C全局变量相对应的数据位置。代码和数据区是直接按照可执行目标文件的内容初始化的。

  • 堆:
    代码和数据区在进程一开始就被指定了大小,而调用malloc和free这样的C标准库函数时,堆可以在运行时动态地扩展和收缩。

  • 共享库:
    存放共享库的代码和数据。

  • 栈:
    实现函数调用。程序执行期间可动态扩展和收缩。

1.7.4 文件

每个I/O设备,都可以看作是文件。系统中所有输入输出,都是通过使用一小组Unix I/O系统函数调用读写文件来实现的。

文件这个概念向应用程序提供了一个统一视图来看待系统中所有的I/O设备。

1.8 系统之间的网络通信

网络可视为一个I/O设备。当系统从主存复制一串字节到网络适配器时,数据流经过网络送到另一台机器。

在这里插入图片描述
在这里插入图片描述

1.9重要主题

1.9.1 Amdahl定律

当我们对系统某个部分加速时,其对系统整体性能的影响取决于该部分的重要性和加速程度。

若系统执行某一程序所需时间为$T_{old} , 假 设 系 统 某 部 分 所 需 执 行 时 间 与 该 时 间 之 比 为 ,假设系统某部分所需执行时间与该时间之比为 a , 而 该 部 分 提 升 比 例 为 ,而该部分提升比例为 k$。因此,总执行时间为:

T n e w = ( 1 − a ) T o l d + ( a T o l d ) / k = T o l d [ ( 1 − a ) + a / k ] T_{new} = (1-a)T_{old}+(aT_{old})/k = T_{old}[(1-a)+a/k] Tnew=(1a)Told+(aTold)/k=Told[(1a)+a/k]

加速比S为:

S = 1 / [ ( 1 − a ) + a / k ] S = 1/[(1-a) + a/k] S=1/[(1a)+a/k]

1.9.2 并发和并行

并发指一个同时具有多个活动的系统。

并行指用并发来时一个系统运行得更快。可在计算机多个抽象层次上运用。

  • 线程级并发:
    在一个程序中执行多个控制流。传统意义上(传统单核处理器),这种并发是模拟出来的,通过操作系统进行上下文切换来实现。
    • 多线程,又称同时多线程:
      允许一个CPU执行多个控制流。
      CPU硬件有多个备份,比如PC和register file。
      常规处理器需要大约20000个时钟做不同线程间的转换。而超线程处理器可在单个周期基础上决定执行哪一个线程。

    • 多核处理器:
      在这里插入图片描述

      将多个CPU集成到一个芯片上。
      所有核都由自己的L1和L2高速缓存,共享L3高速缓存和与主存的接口。其中,L1分为两部分,一部分存储最近取出的指令,另一部分存储数据。
      多处理器的使用可以从两方面提高系统性能:

  • 减少了执行多个任务时模拟上下文切换的需要
  • 使程序运行更快(要求程序以多线程方式书写)
  • 指令级并行
    在较低的抽象层次上,现代处理器可以同时执行多条指令的属性。
    通过使用流水线,将一条指令的执行划分为不同步骤,用处理器的硬件组织成一系列阶段,每个阶段执行一个步骤,使处理器能够达到接近于一个时钟周期一条指令的执行速率。
    如果达到比一个时钟一条指令更快的执行效率,称之为超标量处理器。
  • 单指令、多数据并行,SIMD
    在最低层次上,采用特殊硬件,允许一条指令产生多个可以并行执行的操作。

1.9.3 计算机系统中的抽象

在这里插入图片描述

指令集架构提供了对实际处理器硬件的抽象。使用这个抽象,机器代码程序表现得好像运行在一次执行一条指令的处理器上。

底层硬件远比抽象描述要复杂精细,它并行执行多条指令,但总与那个简单有效的模型保持一致。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值