代码是如何控制硬件的?_如何用代码控制电脑,Golang程序员怎么优雅迈过30K+这道坎

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Golang全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注go)
img

正文

运算器是一个负责算术运算和逻辑运算的模块,主要包含算术逻辑单元(Arithmetic Logic Unit,简称ALU)和浮点运算单元(Floating Point Unit,简称FPU)。ALU的主要功能:在控制信号的作用下,完成加、减、乘、除等算术运算,以及与、或、非、异或等逻辑运算以及移位、补位等运算。通常ALU由两个输入端和一个输出端(两个值输入,一个结果输出)。FPU主要负责浮点运算和高精度整数运算。有些FPU还具有向量运算的功能,另外一些则有专门的向量处理单元。

运算器是用与、或、非逻辑门电路搭建起来的,比如,带进位的二进制加法电路:

img

二进制加法器

运算器主要的处理对象是数据,所以数据的长度以及数据的表示方法,对运算器的影响很大。大多数通用CPU是以16、32、64位数据作为运算器一次处理数据的长度。能够一次性对一个数据的所有位,同时处理的运算器称为并行运算器,一次只能对数据的一个位处理的运算器称为串行运算器。我们通常所说的“CPU是几位的”就是指ALU一次所能处理的数据的位数。

运算器与其他部分的关系:计算机运算时,运算器的操作对象和操作种类由控制器决定。运算器操作的数据从cache或内存中读取,处理的结果再写入内存(或者暂时存放在内部寄存器中),而且运算器对内存数据的读写,是由控制器来进行的。

3) 寄存器

寄存器的主要功能是存储数据、地址及指令,并且能够高速、自动地完成数据的存储。寄存器是有记忆功能的器件,而且采用两种稳定状态0或1来记录数据信息,所以CPU中的程序和数据,都要转换为二进制才可以存储和操作。寄存器也是由与、或、非逻辑门电路组成的,下面就展示1bit的存储,32个bit存储电路就是32个重复的1bit电路。

img

寄存器1bit电路

其中D为寄存器中一个bit输入,B为当前寄存器的一个bit。当WE(Write Enable)为0时,B保持不变,不受D的变化影响。当WE为1时,这时候D为0时,B为0,并将该值存到电路中,当D为1时,B为1,并将该值存到电路中。

2.2 MMU

内存映射单元(Memory Map Unit,简称MMU),指的是将虚拟地址转化成物理地址的模块。MMU包含了两个模块:页表查找表(Table Lookup Buffer,简称TLB)和页表遍历单元(Table Walk Unit,简称TWU)。TLB是一个高速缓存,用于缓存页表转换的结果,从而减少页表查询的时间。一个完整的页表翻译和查找的过程叫做页表查询,页表查询是通过硬件模块TWU自动完成的,但是页表的维护需要软件来完成,且存放在主存中,因此页表查询是一个耗时的过程。当TLB未命中时,MMU才会通过TWU查询页表,从而得到翻译后的物理地址,这个虚拟地址及物理地址的映射也会存储在TLB中。

对于ARM这样的处理器,CPU看到的都是虚拟地址,需要经过MMU转化为物理地址,才能访问cache或者内存,拿到物理地址中的内容。你可能会疑问,为什么需要虚拟内存,直接用物理内存不行吗?是的,不行。为了做进程地址空间的隔离及提升内存的使用效率,使用虚拟内存是很有必要的。后面会专门写一篇文章专门讲述MMU。

2.3 cache

由于CPU与内存之间存在很大的速度差(两者相差上百倍),同时又因为程序的加载有时间及空间局部性的特点,也就是说程序的一个内存位置被访问了,附近的位置很快也会被访问到。那么我们可以把内存中的部分代码提前加载到访问更快的Cache里面。既然Cache的主要作用是CPU与主存的缓冲层,那么Cache的速度应该接近于CPU,基本上是与CPU同频运作。一般缓存都集成在CPU芯片上,L1 cache分为L1D和L1I cache,L1D、L1I和L2 cache在同一个cpu上,L3 cache一般是多个cpu间共享。既然cache的访问速度这么快是不是越大越好,其实并不是,单拿成本和die的面积来说,cache就不能做的太大。后面会专门写一篇文章专门讲述cache。

img

CPU上cache的分布

现代计算机或嵌入式系统的存储设备一般有 Cache、内存、SSD、HDD硬盘。这些存储设备越靠近 CPU 速度越快,容量越小,价格越贵。

  • 寄存器(Register):寄存器与其说是存储器,其实更像是 CPU 本身的一部分,只能存放极其有限的信息,但是速度非常快,和CPU同步。
  • 高速缓存(CPU Cache):使用静态随机存取存储器(Static Random-Access Memory,简称SRAM)的芯片。
  • 内存(DRAM):使用动态随机存取存储器(Dynamic Random Access Memory,简称DRAM)的芯片,比起 SRAM 来说,它的密度更高,有更大的容量,而且它也比 SRAM 芯片便宜不少。
  • 硬盘:如固态硬盘(Solid-state drive 或 Solid-state disk,简称SSD)、硬盘(Hard Disk Drive,简称HDD)。

img

存储金字塔

每一种存储器设备只和它相邻的存储设备打交道。比如,CPU Cache是从内存里加载而来的,或者需要写回内存,并不会直接写回数据到硬盘,也不会直接从硬盘加载数据到CPU Cache中,而是先加载到内存,再从内存加载到Cache中。

可以看出,越是速度快的设备,容量就越小。这里一共 10M 的 Cache,成本只是几十美元。而 8GB 的内存、128G 的 SSD 以及 1T 的 HDD,大概零售价格加在一起,也就和我们的高速缓存的价格差不多。

img

各存储器成本、延时对比

2.4 主存

主存里分别存储了各种数据,包括代码段、数据段、字符串、地址等。它的读写速度相对寄存器、cache慢了很多,但是单位成本却低了很多。通过系统中的存储金字塔设计,利用程序的时间及空间局部性原理,可以很好地利用主存的价格优势,弥补读写时间慢的问题。后面会专门写一篇文章讲解主存。

2.5 BUS

虽然从上面的框图上不能直观地看到BUS总线的存在,但是地址、数据的传输都是依赖总线完成的。它就像一条高速公路,快速完成各个单元间的数据交换,也是数据从内存流进和流出CPU的地方。CPU总线(前端总线)传输速率决定着CPU与内存之间传输数据的速度快慢。CPU总线速率越高,CPU从内存取指令和数据的等待时间越少,运行程序速度越快。总线又细分成数据总线、地址总线和控制总线。后面会专门写一篇文章讲解总线相关的知识。

3,CPU的运行过程

3.1 指令集

指令集架构(Instruction Set Architecture,简称ISA)是CPU和软件之间的桥梁。ISA包含指令集、特权级、寄存器、执行模式、安全扩展、性能加速扩展等方面。其中,指令集是ISA的重要组成部分,通常包含一系列不同功能的指令,用于数据搬移、计算、内存访问、过程调用等。CPU在运行操作系统或者应用程序的时候,实际上是在执行它被编译后所包含的指令。根据执行指令的特征,CPU分为精简指令集计算机(Reduced Instruction Set Conputer,简称RISC)和复杂指令集计算机(Complex Instruction Set Conputer,简称CISC)。

img

RISC 与CISC的对比

RISC类CPU的指令功能单纯,种类少。相对地,CISC类CPU指令功能复杂,种类繁多。RISC指令精简的好处是,CPU内部构造可以简化,适合高速操作,但是在进行相同的操作时,由于每条指令功能单纯,所以与CISC相比,RISC需要使用更多的指令数量。虽然CISC的内部构造复杂不适合高速操作,但进行相同处理时指令数比RISC要少。

RISC架构最大的特点是,只使用载入和存储指令访问内存,这种架构成为载入存储架构。这样做的好处是可以简化指令集和流水线的设计,在这种架构下,运算指令只能对寄存器中的数据进行操作。RISC和CISC两种架构各有所长,在追求高速运行的CPU领域中,RISC被认为更具优势。虽然这些年,Intel和AMD两家公司的CPU指令集依然是CISC的,但内部却将复杂指令分解成简单指令,使得内部像RISC一样工作。

3.2 CPU一般运行过程

CPU从cache或主存中取出指令,然后放入指令寄存器,控制器对该指令进行译码。最终把指令分解成一系列的微操作,然后发出各种控制命令,执行微操作序列,从而完成一条指令的执行。指令是CPU规定执行操作的类型和操作数的基本命令。指令是由一个字节或者多个字节组成(对于arm64,指令长度是4个字节),其中包括操作码字段、一个或多个有关操作数地址的字段以及一些表征机器状态的状态字以及特征码。有的指令中也直接包含操作数本身,且用二进制序列表示。指令的构造如下:

img

指令构造

1)取指

取指令(Instruction Fetch,简称IF)阶段是将一条指令从cache或主存中获取指令到指令寄存器的过程。CPU中有一个程序计数器(Program Counter,简称PC)寄存器,其中保存着将要执行指令的地址。指令读取是通过将PC寄存器的值,输出给cache或者内存,然后由cache或内存返回该值对应地址中的指令。当一条指令被取出后,PC中的数值将根据指令字长度自动递增。

2) 译码

取出指令后,CPU会立即进入指令译码(Instruction Decode,简称ID)阶段。在指令译码阶段,指令译码器按照预定的指令格式,对取回的指令进行拆分和解释,识别区分出不同的指令类别以及各种获取操作数的方法。指令有很多种,有进行各种运算的指令、控制下一条命令的指令、对内存进行读写的命令,还有对CPU进行控制的指令。

3) 执行

在取指令和指令译码阶段之后,接着进入执行指令(Execute,简称EX)阶段。此阶段的任务是完成指令所规定的各种操作,实现具体指令的功能。为此,CPU的不同部分的组件被连接起来,以执行所需的操作。例如,执行一个加法运算,ALU将会连接到一组输入和一组输出。输入提供了要进行相加运算的数值,而输出求和后的结果。如果加法运算产生一个对该CPU处理而言过大的结果,在标志暂存器里,运算溢出(Arithmetic Overflow,简称AO)标志可能会被设置。

4) 访存

根据指令需要,有可能要访问主存,读取操作数,这样就进入了访存取数的阶段。此阶段的任务是:根据指令中的地址码,经过MMU将虚拟地址转化成物理地址,根据物理地址得到操作数在cache或主存中的地址,并从cache或主存中读取该操作数用于运算。

5) 写回

结果写回(Write Back,简称WB)阶段,一般把执行指令阶段的运行结果数据,写回到内部寄存器中,以便被后续的指令快速地存取。在有些情况下,结果数据也可被写入相对较慢、但较廉价且容量较大的主存。许多指令还会改变程序状态寄存器中标志位的状态,这些标志位标识着不同的操作结果,可被用来影响程序的动作。在指令执行完毕、结果数据写回之后,若无意外事件(如结果溢出等)发生,CPU就接着从程序计数器PC中取得下一条指令地址,开始新一轮的循环,下一个指令周期将顺序取出下一条指令。

3.3 CPU中断流程

在正常情况下,CPU 可以顺序执行,也可以分支执行,这些总归是按照既定顺序去执行。现实中,有时需要暂时中断CPU的当前执行流,让CPU去做点其他的工作,再回头来继续原来的执行流。因此CPU硬件提供了一种中断机制,可以先让CPU停下,等异常或中断服务程序执行完后,再切回来:

  • 保存PC:保存当前的 PC 的值到内存的某个位置
  • 修改PC:修改 PC 的值,让执行其他执行流
  • 回原PC:其他执行流执行结束之后,通过将刚才保存的 PC 值恢复到 PC 寄存器
  • 继续原执行流:继续中断前的执行流

通过以上CPU的框架及CPU的运行过程是不是基本上明白了软件是怎么控制硬件运行的?其实,虽然软件控制的硬件种类繁多,但是基本上都是相通的。关键是理解cpu是怎么运行的,然后怎么产生相关的控制信号。


不知道题主学过数字电路没有,学过就比较好理解了。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
难做到真正的技术提升。**

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-FwQ4rhqA-1713191528594)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值