关于后端:大白话带你打开操作系统大门

3次阅读

共计 4733 个字符,预计需要花费 12 分钟才能阅读完成。

所有的起源 图灵机

图灵机次要由数据存储单元,管制单元,运算单元和一个可读写内部数据的读写头几局部形成。
图灵机工作须要有一条纸带,纸带下面布满格子,能够在格子下面记录字符,字符可分为数据字符和指令字符;纸带穿过图灵机并一直向前挪动;图灵机上的读写头顺次读取纸带格子上的字符,依据管制单元辨别读取的字符属于数据还是指令,当读到数据字符时,将字符存储到存储单元中,当读到指令字符时,运算单元会将存储单元中的数据读取进去并进行相应运算,并将后果通过读写头写入纸带的下一个格子中。

图灵机的根本工作模式跟现在的计算机是一样的,数据和指令存在存储器中(纸带和存储单元),处理器读取后运算得出后果。计算机中应用 cpu 进行指令计算,存放数据的存储器咱们常听的有磁盘、SSD、内存。但 cpu 并不间接从这些存储器中读取并执行指令,而是采纳分级缓存策略。

存储器分级

为什么须要分级

咱们比拟相熟的磁盘,数据在断电之后还能保留着,而且磁盘的存储空间较大,通常能有上 T 容量,但其数据读取速度极慢;内存的读取速度尽管比磁盘快了将近 100 倍,但跟 cpu 的执行速度相比,还是属于”龟速“。此外,内存是按在主板上的,数据通过电路板传输到 cpu 上,数据传输的耗时绝对于 cpu 执行速度来说也是不可漠视的。

存储器体积越小,其存储容量就会受到限制;读写速度越快,能耗和老本也会越高;其次,存储器间隔 cpu 越远,数据传输也越大。所以,目前而言,应用繁多存储器无奈让存储器中的数据跟的上 cpu 的处理速度。

计算机采纳的计划是将存储器分级,将 cpu 应用频率越高的数据,寄存在读写速度越快,间隔 cpu 更近的存储器(缓存)中;将应用频率较低的数据寄存在读写速度较慢,间隔 cpu 较远,但存储容量较大,老本较低的存储器中。这样,cpu 读取数据时,间接先从缓存中读取,缓存中不存在再从间隔更远的存储器中读取。

分级缓存计划的可行性在于计算机存在局部性原理,试想下咱们平时写的代码程序,运算用的最多的是 for 循环,而后对定义的几个变量进行计算读写。所以,cpu 执行一个程序的时候,有几个数据区域的读写频率是比拟高的。所以,能够将这些「热点」区域的数据缓存起来,下次读取的时候就会快很多。据统计,存储器缓存命中率能达到 95%,也就是只有 5% 的数据会穿透到内存。

存储器分级策略

通常,存储器分成以下几个级别:

  • 寄存器
  • CPU cache:

    • L1-cache
    • L2-cache
    • L3-cache
  • 内存
  • 磁盘 /SSD

磁盘 /SSD

SSD/ 磁盘是间隔 CPU 最远,读取速度最慢的一类存储器,长处在于老本较低,断电后数据还在。其中 SSD 是咱们常说的固态硬盘,构造与内存相似,读写速度比内存慢 10-1000 倍;磁盘读取速度更慢,比内存慢 100W 倍左右,随着 SSD 的遍及,曾经缓缓被取代了。

内存

内存是插在主板上,与 CPU 有一段距离,CPU 通过主板总线读取内存中的数据,造价比磁盘稍贵,但读取速度比磁盘快,速度大略在 200-300 个 CPU 周期;容量方面,个人电脑的内存个别是 8 -16G,服务器上的内存能够达到几个 T。

CPU 周期:一条指令可分为取指令,执行指令等若干个阶段,每个阶段实现所需的工夫成为 CPU 周期。

CPU cache (CPU 高速缓存)

CPU cache 存在于 CPU 外部,CPU cache 可分为 L1 (一级缓存)、L2 (二级缓存)、L3 (三级缓存),CPU 的每个核都有各自的 L1 和 L2 缓存,同一个 CPU 的多个核共享一个 L3 缓存。

  • 与 CPU 间隔:L1 < L2 < L3
  • 容量:L1(几十~几百 KB)<L2 (几百 KB~几 MB) < L3 (几 MB~几十 MB)
  • 读写速度:L1(2-4CPU 周期 ) > L2 (10-20CPU 周期) > L3 (20-60CPU 周期)


L1 缓存划分了指令区和数据区,下文会解释

须要留神的是,cpu 缓存中每个缓存的最小单位是内存的一个内存块,而不是缓存一个变量;cpu 缓存和内存的映射形式有很多种,相似于 cache 行号 = 内存页号 mod cache 总行数;这样,先依据内存地址计算出地址所在内存页号,再通过映射关系算出 cache 行号,如果存在缓存中,间接获取数据即可,如果不存在再到内存中获取。

寄存器

寄存器是 CPU 理论进行指令读写的中央,是间隔 CPU 最近的存储器,读写速度也是最快,能在半个 CPU 周期实现读写;一个 CPU 中寄存器数量在几十到几百个之间,每个寄存器容量很小,只能存储肯定字节(4-8 个字节)的数据。

32 位 CPU 中大多数寄存器能够存储 4 个字节 64 位 CPU 中大多数寄存器能够存储 8 个字节

寄存器依据用处不同,可分为好几类,为了便于前面指令执行过程学习,咱们先理解以下几类:

  • 通用寄存器:用于存储程序参数数据。
  • 指令寄存器:每条 CPU 执行的指令,会先从内存中读入指令寄存器中,而后再让 CPU 读取执行。
  • 指令指针寄存器:寄存着 CPU 下一条要执行的指令所在的内存地址,CPU 依据指令指针寄存器中的指令内存地址,将指令读入指令寄存器中。指令指针寄存器也成为 IP 寄存器。
  • 段寄存器:为了可拜访更大的物理空间,CPU 通过根底地址 + 偏移量定位一个物理内存地址。段寄存器中存储的是基地址信息。CS 是寄存指令地址的一个段寄存器,与 IP 寄存器一起定位指令在内存中的地址。

    假如一个寄存器最大存储 4 字节数据,4 字节 = 4*8=32 位,值示意范畴:0~(2^32) -1,换算单位为 4G,也就是这个寄存器最大能查找 0-4G 范畴的地址,但咱们之前提到的内存容量可达几 T,所以,间接通过一个寄存器无奈示意全副范畴的内存地址。采纳“根底地址 + 偏移地址 = 物理地址”的寻址模式,可极大扩充内存寻址能力。例如:32 位的根底地址左移 32 位,再加上 32 位的偏移地址,可示意 64 位(16EiB)的内存地址。须要留神的是,计算机的最终寻址范畴是由上面介绍的地址总线决定的。

总线 – CPU 与外界的桥梁

按下面的存储器分级,数据先从磁盘加载到内存中,而后被读取到 CPU 外部的高速缓存和寄存器中,CPU 读取寄存器进行解决。其中,CPU 和 CPU cache 之间的数据读写是在 CPU 外部中实现的,CPU 对内存的读写则是通过主板上的总线实现的。

总线能够看成是多根导线的汇合,通过管制导线电压的高下来传递数据,高电压是 1,低电压是 0。

依据传输信息的不同,总线分为地址总线,数据总线和管制总线

试想“向内存 3 地位读取数据”这一条读指令蕴含了几个信息:

  • 操作的内存地位是 3(地址信息)
  • 操作的命令是读命令(管制信息)
  • 数据传输(数据信息)

3 类总线别离负责对应信息的传输:CPU 通过地址总线将要操作的内存地址信息传递给内存;通过管制总线收回内存读命令;内存将数据从数据总线传入 CPU。

地址总线

讲地址总线之前,咱们先讲讲存储器地址的划分。存储器会被划分为若干个存储单元,存储单元从零开始编号,这些编号能够看做是存储单元在存储器中的地址。

每个存储单元由 8 个位 (bit) 组成,也就是能够存储一个字节的数据;假如一个存储器有 128 个存储单元,能够存储 128 个字节 (Byte)。

CPU 通过地址总线来指定存储单元,地址总线的线数,决定了对内存的寻址范畴。比方,一个 CPU 有 16 根地址总线,最多能够寻找 2 的 16 次方个内存单元。

假如一个 16 位的 CPU 有 20 条地址总线,16 位的 CPU 如何一次性给出 20 位的地址呢?

其实答案后面曾经给出了,CPU 外部会通过「根底地址」+「偏移地址」的办法合成一个 20 位的地址。

数据总线

CPU 与内存或其余器件通过数据总线进行数据传输,数据总线的宽度 (总线条数) 决定了 CPU 与外界的数据传输速度。8 根数据总线一次可传输一个字节 (8bit) 的数据,16 根数据总线一次可传输两个字节 (16bit)。

管制总线

CPU 对外部器件的管制是通过管制总线来进行的,多少根管制总线,意味着 CPU 对外部器件有多少种管制,所以管制总线的宽度决定了 CPU 对外部器件的控制能力。

指令执行

理解了各种存储器和总线,咱们再来看看程序是如何从磁盘加载到内存而后被 CPU 执行的。

咱们编写的程序须要先通过编译器翻译成 CPU 意识的指令,这个过程称为指令的结构。程序启动时,会将程序的指令和数据别离存在两个内存段中。同时,PC 指针(IP 寄存器 + CS 寄存器)会指到指令段的起始地址(就是将起始地址赋值到 PC 指针上),示意 CPU 将从这个地址开始读取内存中的指令并执行。

指令解析

指令先被读取到指令寄存器中,CPU 取出执行时,须要先对指令进行解析。

咱们都晓得,内存中寄存的内容都是二进制类型(下面的指令咱们写成 16 进制),cpu 读取到要执行的指令后,会先对二进制的指令进行解析。以下面“0x8c400104”为例,拆分成二进制:


下面指令分成操作码、寄存器编号、内存地址三局部:

  • 最右边 6 位,称为操作码,“10011”示意 load 指令。
  • 两头 4 位,指定了寄存器的编号,“0001”示意 R1 寄存器。
  • 最初的 22 位示意要操作的内存地址。

所以,这条指令是指将指定内存地址的内容加载到寄存器 R1 中。
总结一下,程序执行时:

  1. 程序的指令和数据别离存入内存指令段和数据段中,PC 指针指到指令段的起始地址。
  2. CPU 读取 PC 指针指向的指令存入指令寄存器中。
    a. CPU 通过地址总线指定要拜访的内存地址;通过管制总线发送“读指令”。
    b. 内存通过数据总线将数据传入 CPU,CPU 将这个数据存到指令寄存器中。
  3. CPU 解析指令寄存器中的指令内容。
  4. CPU 通过运算单元和管制单元执行指令。
  5. PC 指针自增,指向下一条指令内存地址。

所以,取址、译码、执行,这是一个指令的执行周期,所有指令都会严格依照这个程序执行。

指令预读

CPU 执行指令的速度是十分快的,但内存的读写是十分慢的,所以,如果从内存中一条条读取指令再执行的话,指令执行周期会变得很慢。

后面咱们学到,CPU 外部还有三级缓存,所以,咱们能够将内存中的多条指令一次性先读到读写速度较快的 L1 缓存中,这样,取址速度就能跟的上 CPU 的指令执行速度了。

同时,为了防止数据缓存笼罩指令缓存影响指令执行,咱们能够将 L1 缓存划分为指令区和数据区。

思考下 L2 和 L3 须要划分指令区和数据区吗?其实是不须要的,因为 L2 和 L3 并不需要帮助指令预读。

如何更快的执行指令

为了更快的执行指令,咱们须要应用 CPU 的指令流水线技术。

在方才的流程中,取指,解码的时候运算单元是闲暇的,为了进步指令处理速度,须要让运算单元就能够始终处于运算中。咱们能够应用 CPU 的指令流水线技术,在第一条指令实现取址进行译码时,第二条指令立即进行取址,顺次类推,这样,在上一条指令实现执行后,下一条指令也实现译码能够进行执行了。

一句话总结

程序存储在存储器中,cpu 读取指令并进行执行计算。

因为 cpu 的指令执行速度极快,目前没有存储器能同时满足读写速度快,散热小,能耗低,容量大等要求,所以采纳存储器分级策略,应用多级缓存来匹配上 cpu 的执行速度。

cpu 与内存之间的数据传输通过主板上的总线来实现。通过地址总线将要操作的内存地址信息传递给内存;通过管制总线收回命令类型;内存将数据从数据总线传入 CPU。

寄存器是 cpu 间接读取指令和参数数据的存储器。寄存器按用处可分为好几类。对于数据,会先将数据读到通用寄存器中,之后 CPU 从通用寄存器中读写数据;对于指令,CPU 会先依据 CS 段寄存器和指令指针寄存器独特指向的指令内存地址获取指令,并将指令存入指令寄存器中,之后 CPU 再从指令寄存器中读取执行。

指令的执行包含取址、译码、执行。为了防止 CPU 每次获取指令都得从内存中获取,能够先将指令预读到 CPU L1-Cache 中;同时,为了让 CPU 的计算单元始终处于运算状态,能够应用流水线技术。

写在最初

喜爱本文的敌人,欢送关注公众号「会玩 code」,专一大白话分享实用技术

正文完
 0