关于之前「Go语言的内存管理实现」这部分,本来接下来是要给大家继续讲解「Go语言堆内存、栈内存分配」的,以及这部分之前图都画完了。但是呢,写文章的时候,写着写着发现写不下去了,为什么?
我发现想要彻底理解「Go语言堆内存、栈内存分配」必须需要很清楚的理解:什么是堆内存和栈内存,看到这里肯定很多朋友笑了「堆内存/栈内存」那不简单么:
确实,上面的说法没什么问题。但是呢,本着刨根问底的态度,我再来引申几个问题:
为了彻底帮助大家简单明了的吃透「堆内存、栈内存」,又不断引申出了新的问题:
我们写的代码、以及运行起来的程序到底是什么?
在解决这个问题的时候,却又引申出了新的问题:
刨根问底,计算机到底是怎么运行起来的?
最后这样一步步引申到了「计算机原理」和「计算机的发展史」,为了更好理解这些问题,于是这两个月我又读了三本书,具体如下:
我把读完这三本书学习到的知识点进行整理,以及结合自己的理解,抽丝拔茧帮助大家去理解:
搞定了这些问题,我们再去学习「Go语言堆内存、栈内存」或者别的语言的「堆内存、栈内存」都会得心应手,容易很多。
本篇文章是自己对这两个月学习内容的总结,同时也帮助大家对计算机发展历史有一个基本的认知,本文主要目录如下:
上个世纪伟大的数学家们发起了一个挑战大概意思是:“制造一台机器可以自动计算数学问题”。当时伟大的数学家艾伦·图灵提出了自己的理论,这个理论就是大名鼎鼎的“图灵机”,艾伦·图灵就是理论计算机“图灵机”的创造者。
不难理解,数学问题都可以转化为两类问题:
算术问题可以通过逻辑运算解决,所以所有数学问题都可以看作是逻辑问题。所以,只要找到可以自动判定真假的某种机器即可实现自动计算。
这里就有人疑惑🤔了,逻辑问题怎么解决算术问题的,想要理解这个问题我们先回到小学加法运算,比如16+36的计算过程:
16
36
+
------
2
4 1(进位)
------
52
这个运算过程我们只需要重点关注以下几点:
目前进位的问题已经可以转化为逻辑问题了。以上是十进制的加法运算过程,我们换成更简单二进制加法运算再来看看,如下:
二进制相对于十进制更加简单,只有0和1两个状态,简单回顾下二进制的加法运算过程:
为了简化理解这里以十进制 3 + 6 的二进制运算过程为例:
二进制分别为:
0011
0110
A:被加数
B:加数
C:进位,当前位运算后的进位结果,有进位则进位值为1,无进位则进位值为0
D:结果,当前位运算结果
C1:进位,上一位运算后的进位
二进制计算过程:
<------从右到左最低位开始逐位运算------
A 0 0 1 1
^ 按位异或运算
B 0 1 1 0
---------------------计算第1位
D 1
C 0
C1 0
^
A 1
^
B 1
---------------------计算第2位
D 0
C 1
C1 1
^
A 0
^
B 1
---------------------计算第3位
D 0
C 1
C1 1
^
A 0
^
B 0
---------------------计算第4位
D 1 0 0 1
左右滑动查看
A | B | C1 | D 结果 | C 进位 |
---|---|---|---|---|
- | - | - | A异或B异或C1 | (A与B)或者(A与C1)或者(B与C1) |
1 | 0 | 0 | 1 | 0 |
1 | 1 | 0 | 0 | 1 |
0 | 1 | 1 | 0 | 1 |
0 | 0 | 0 | 1 | 0 |
以上过程把十进制 3 + 6 的算术运算完全转化为了逻辑问题,所以只要找到可以自动判定真假的某种机器即可实现自动计算。
上个世纪电子学开始广泛发展,晶体管的诞生为理论上的「自动的机器」指明了新的方向🧭。晶体管有两个状态,分别是:
接着,数学家&电子学家们用多个晶体管构成门电路:
这样就实现了可以「自动判定逻辑问题的真假的设备」,同时数学家和电子学家们又通过多个门电路实现了半加器、全加器、全减器、乘法器等实现算术运算:
这样后面就诞生了世界上第一台真正意义的计算机。
上面诞生了硬件,也就是真正意义的计算机。问题是如何编写程序?我们的程序其实就是门电路中的晶体管不断的运行导通1和截止0两个状态之间,对应的文本代码其实就是数字0和1,所以早期的代码就是直接编写0和1的代码。但是对于人类阅读友好的永远是具备描述性的具备可读性的文本,于是诞生了更适合人们阅读和编写的汇编代码。
人们把中央处理器CPU可以运行的一系列指令集合分别命名了具备可读性的文本,这样就诞生了由助记符和操作数等组成的汇编语言。通常来看CPU一般具备四类指令,分别为:
简单来看就这些类别的指令,分别给它们用更适合人类阅读文本替代0和1,比如MOV指令代表传输数据、jmp指令代表跳转到代码任意位置。
同时人们发明了编译器自动把汇编代码转换为0和1组成的机器代码。
同时人们发现编写程序过程中,发现经常会出现重复性的逻辑编写,比如算术平方根。为了提高效率和复用,就诞生了子函数和函数库的概念。
随着计算机技术和编程技术的快速发展,逐步诞生了更高效的编程语言、以及集成开发环境等等。
先来看看计算机的组成:
最早工程师编写的程序是可以直接操作这些硬件设备的:
存在问题:每个编写程序的工程师都要实现对这些硬件的操作,存在大量重复的工作,以及安全性等等问题。
于是对硬件设备的操作进行统一的封装,比如对输入/输出设备的操作,对磁盘的操作等等,这样就形成了一系列统一的API以及应用程序,提升了开发效率也保证了安全等等。
这就是操作系统:封装了一系列对计算机硬件设备操作的API和应用程序的集合。
简化版计算机的关键发展点:
编程语言的关键发展点:
本文从一些关键点回顾了计算机的发展史,为后面理解程序的运行打好基础。下篇文章我们就来看看:
我们写的代码到底是什么?