GDB工具分析golang源码

整体引导顺序:

GDB工具分析golang源码line 8

GDB工具分析golang源码

根据:asm_amd64.s文件的内容,以下go文件被顺序调用:先call一些初始化,最后调用runtime的main。

在runtime.main() 中:执行栈最大限制,启动垃圾回收,执行runtime包内所有初始化init,启动垃圾回收后台操作,执行所有的用户包,包括标准库,的初始化init,执行用户逻辑入口main.main函数。执行结束,返回退出状态码。

//go:linkname runtime_init runtime.init  表示由编译器动态生成

func runtime_init()

编译器动态生成的方法还有:func main_init()

GDB工具分析golang源码

GDB工具分析golang源码

 

所有init会在同一个go程执行,所有init结束后才会执行main


安装gdb和写一个测试函数main.go;编译成test;gdb test调试test文件。

1.汇编针对特定平台的引导

注意源码文件中的中间的.,要写成最下的.

GDB工具分析golang源码GDB工具分析golang源码

GDB工具分析golang源码GDB工具分析golang源码

GDB工具分析golang源码


2.初始化

至此 汇编平台针对go平台的引导过程完成。

整个初始化过程比较繁琐,要完成诸如命令行参数整理,环境变量设置,内存分配器,垃圾回收器,和并发调度的现场准备。

GDB工具分析golang源码

  • 根据如下过程,初始化的runtime:

GDB工具分析golang源码

b runtime.args  整理命令行参数

Breakpoint 6 at 0x436230: file /home/yz/go/goroot/go/src/runtime/runtime1.go, line 60.

b runtime.osinit   确定cpucore数量

Breakpoint 7 at 0x4264e0: file /home/yz/go/goroot/go/src/runtime/os_linux.go, line 277.

b runtime.schedinit 我们关注的所有运行时环境初始化构造都在这里呗调用

Breakpoint 8 at 0x42a8f0: file /home/yz/go/goroot/go/src/runtime/proc.go, line 526.

GDB工具分析golang源码

最大系统线程数限制为:10000

goargs() goenvs()处理命令行参数和环境变量

gcinit()垃圾回收器初始化      

procs := ncpu//通过cpu core 和gomaxprocs环境变量确定p数量,默认是cpu个数
    if n, ok := atoi32(gogetenv("GOMAXPROCS")); ok && n > 0 {
        procs = n
    }
    if procresize(procs) != nil {
        throw("unknown runnable goroutine during bootstrap")
    }

内存分配器、垃圾回收器,并发调度器的初始化细节需要很多专属特征,先不去理会。

  • 进入 runtime.main

runtime/proc.go line110

3.内存分配

所有内置运行时的编程语言通常会抛弃传统的内存分配方式,该自主管理。这样可以完成类似预分配,内存池等操作。以避开系统调用带来的性能问题,而且,可以更好滴配合垃圾回收。

go的内存分配策略:

1.每次从os申请一大块内存如1MB,以减少系统调用;2.把申请导的大块内存按照特定大小预先分成小块,构成链表。

3.为对象分配内存时,从链表提取一个小块;4.回收内存对象时候,把小块重新归还到链表

5.如闲置内存过多,则偿还部分给os.

内存分配至管理内存块,不关心对象状态。且不会主动回收内存,由垃圾回收清理后,触发内存分配回收操作。