学习笔记: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.将源代码分析成Token
2.Token是代码中的最小语义结构
句法分析:
1.Token序列经过处理,变成语法树(抽象语法树ast)
语义分析:
1.类型检查
2.类型推断
3.查看类型是否匹配
4.函数调用内联
5.逃逸分析
中间码生成(SSA)
1.为了处理不同平台的差异,先生成中间代码(SSA)
2.查看从代码到SSA中间码的整个过程
|
|
代码优化:
各个步骤都会存在
机器码生成:
1.先生成plan9汇编代码
2.最后编译为机器码
3.输出的机器码为.a文件
4.查看plan9汇编代码:
|
|
链接:
将各个包进行链接,包括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() 也是在协程中运行的