Contents

学习笔记:Go的runtime,Go的编译过程,Go的运行过程

什么是Runtime?

就是程序的运行环境。

Go的Runtime特点:

1.没有虚拟机的概念

2.Runtime作为程序的一部分打包进二进制文件

3.Runtime随用户程序一起运行

4.Runtime与用户程序没有明显界限,直接通过函数调用

Go的Runtime能力:

1.内存管理能力

2.垃圾回收能力(GC)

3.超强的并发能力(协程调度)

Go的Runtime其他特点:

1.Runtime有一定的屏蔽系统调用能力

2.一些go的关键字其实是Runtime下的函数

总结

1.Go的Runtime负责内存管理,垃圾回收,协程调度

2.Go的Runtime被编译为用户程序的一部分,一起运行

Go是如何编译的?

编译命令:

1
go build -n

编译过程:

词法分析——>句法分析——->语义分析——->中间码生成——->代码优化——->机器码生成———>链接

词法分析:

1.将源代码分析成Token

2.Token是代码中的最小语义结构

句法分析:

1.Token序列经过处理,变成语法树(抽象语法树ast)

语义分析:

1.类型检查

2.类型推断

3.查看类型是否匹配

4.函数调用内联

5.逃逸分析

中间码生成(SSA)

1.为了处理不同平台的差异,先生成中间代码(SSA)

2.查看从代码到SSA中间码的整个过程

1
2
3
$env:GOSSAFUNC="main"
export GOSSAFUNC=main
go build

代码优化:

各个步骤都会存在

机器码生成:

1.先生成plan9汇编代码

2.最后编译为机器码

3.输出的机器码为.a文件

4.查看plan9汇编代码:

1
go build -gcflags -S main.go

链接:

将各个包进行链接,包括runtime

总结:

1.编译前端:词法分析,句法分析,语义分析

2.编译后端:中间码生成,代码优化,机器码生成

3.链接

Go程序是如何运行的?

A:程序的入口是main方法吗?:

不是的。是runtime包下的rt0_XXX.s(不是go程序,是一个汇编语言)

B:运行步骤:

1.读取命令行参数

复制参数数量argc和参数值argv到栈上

2.初始化g0执行栈

a.g0是为了调度协程而产生的协程

b.g0是每个Go程序的第一个协程

3.运行时检测

a.检查各种类型的长度

b.检查指针操作

c.检查结构体字段的偏移量

d.检查atomic原子操作

e.检查CAS操作

f.检查栈大小是否是2的幂次

4.参数初始化 runtime.args

a.对命令行中的参数进行处理

b.参数数量赋值给argc int32

c.参数值赋值给argv **byte

5.调度器初始化 runtime.schedinit

a.全局栈空间内存分配

b.加载命令行参数到 os.Args

c.堆内存空间的初始化

d.加载操作系统环境变量

e.初始化当前系统线程

f.垃圾回收器的参数初始化(GC)

g.算法初始化(map,hash)

h.设置 process 数量

6.创建主协程

a.创建一个新的协程,执行 runtime.main

b.放入调度器等待调度

7.初始化 M

a.初始化一个M,用来调度主协程

8.主协程执行主函数

a.执行runtimem 包中的 init 方法

b.启动 GC 垃圾收集器

c.执行用户包依赖的 init 方法

d.执行用户主程序 main.main() (main包中的main函数)

C:总结

1.Go 启动时经历了检查,各种初始化,初始化协程调度的过程

2.main.main() 也是在协程中运行的