系统初始化流程
首先确定程序启动位置,当前编译过后可执行文件名称为 main
- 使用readelf -h /main 找到程序启动位置
- 使用dlv exec /main 调试代码,在上述启动位置使用 b * 命令打上断点
- dlv中使用si跳转到下一个位置。
这样就找到了启动文件在 ../golang/src/runtime/rt0_linux_amd64.s:8
[root@c4ddfe6f8f1e /]# dlv exec ./main
Type 'help' for list of commands.
(dlv) b *0x45cfa0
Breakpoint 1 set at 0x45cfa0 for _rt0_amd64_linux() .usr/lib/golang/src/runtime/rt0_linux_amd64.s:8
(dlv) c
> _rt0_amd64_linux() .usr/lib/golang/src/runtime/rt0_linux_amd64.s:8 (hits total:1) (PC: 0x45cfa0)
Warning: debugging optimized function
3: // license that can be found in the LICENSE file.
4:
5: #include "textflag.h"
6:
7: TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
=> 8: JMP _rt0_amd64(SB)
9:
而后,使用si进入下一步
(dlv) si
> _rt0_amd64() .usr/lib/golang/src/runtime/asm_amd64.s:15 (PC: 0x459ae0)
Warning: debugging optimized function
10: // _rt0_amd64 is common startup code for most amd64 systems when using
11: // internal linking. This is the entry point for the program from the
12: // kernel for an ordinary -buildmode=exe program. The stack holds the
13: // number of arguments and the C-style argv.
14: TEXT _rt0_amd64(SB),NOSPLIT,$-8
=> 15: MOVQ 0(SP), DI // argc
16: LEAQ 8(SP), SI // argv
17: JMP runtime·rt0_go(SB)
18:
19: // main is common startup code for most amd64 systems when using
20: // external linking. The C startup code will call the symbol "main"
(dlv)
由此可得启动步骤:
- runtime._rt0_amd64_linux
- runtime._rt0_amd64
- runtime.rto_go
在runtime.rto_go中,执行了程序初始化相关步骤并开始进入调度循环
- argc、argv处理
- 全局m0、g0初始化
- 获取CPU核心数
- 开始执行用户main函数
......
CALL runtime·args(SB)
CALL runtime·osinit(SB)
CALL runtime·schedinit(SB)
// create a new goroutine to start program
MOVQ $runtime·mainPC(SB), AX // entry
......