Golang源码探索(一) 编译和调试源码(转)

GO能够说是近几年最热门的新兴语言之一了, 通常人看到分布式大数据就会想到GO,
这个系列的文章会经过研究golang的源代码来分析内部的实现原理,
和CoreCLR不一样的是, golang的源代码已经被不少人研究过了, 我将会着重研究他们未提到过的部分.javascript

另外一点和CoreCLR不一样的是, golang的源代码很是易懂, 注释也很是的丰富,
很明显Google的工程师在写代码的时候有考虑其余人会去看这份代码.html

尽管代码很是易懂, 研究它们仍是须要实际运行和调试才能获得更好的理解,
这个系列分析的golang源代码是Google官方的实现的1.9.2版本, 不适用于其余版本和gccgo等其余实现,
运行环境是Ubuntu 16.04 LTS 64bit.java

编译golang源代码

go的源代码是用go写的, 编译也须要一个可运行的go.
首先咱们从官网下载源代码和二进制文件.linux

go1.9.2.src.tar.gz
go1.9.2.linux-amd64.tar.gzgit

注意两个压缩包解压出来文件夹名称都是go, 咱们解压到如下目录:golang

源代码: ~/git_go/go_src
二进制: ~/git_go/go_bin

编译go以前须要设置环境变量,
GOROOT_BOOTSTRAP是go二进制文件夹的所在目录,
GO_GCFLAGS是编译go时使用的参数.web

export GOROOT_BOOTSTRAP=~/git_go/go_bin export GO_GCFLAGS="-N -l"

这里的-N参数表明禁止优化, -l参数表明禁止内联, go在编译目标程序的时候会嵌入运行时(runtime)的二进制,
禁止优化和内联可让运行时(runtime)中的函数变得更容易调试.bash

都准备好之后就能够进入go的源代码文件夹执行all.bash编译了:markdown

编译的结果在~/git_go/go_src/bin下:分布式

调试golang源代码

以前CoreCLR的系列中我使用了lldb, 在这个系列中我继续沿用这个调试器.
这个系列中使用的是lldb 4.0.

以如下源代码(hello.go)为例:

package main import ( "fmt" "time" ) func printNumber(from, to int, c chan int) { for x := from; x <= to; x++ { fmt.Printf("%d\n", x) time.Sleep(1 * time.Millisecond) } c <- 0 } func main() { c := make(chan int, 3) go printNumber(1, 3, c) go printNumber(4, 6, c) _, _ = <- c, <- c }

编译源代码使用如下命令, 这里的-l参数的意思和上面同样, 若是有须要还能够加-N参数:

~/git_go/go_src/bin/go build -gcflags "-l" hello.go

编译后使用lldb运行:

lldb ./hello

go里面的函数符号名称的命名规则是包名称.函数名称, 例如主函数的符号名称是main.main, 运行时中的newobject的符号名称是runtime.newobject.
首先给主函数下一个断点而后运行:

能够看到成功的进入了主函数, 而且有源代码提示.
接下来给按文件名和行数来下断点:

而后查看函数的汇编代码:

关于lldb的命令能够查看这篇文档.
在我使用的环境中lldb能够正常的下断点, 步进和步过go代码或者汇编指令,
打印变量输出的值有多是错的, 即便不开启优化.

虽然打印变量这个功能很差用, 咱们仍然能够直接让go输出咱们想要的值,
例如修改runtime/malloc.go输出当前环境下arena|spans|bitmap区的大小:

修改后进入src并执行./make.bash, 而后从新编译目标程序, 运行:

能够看到当前环境下arena是512G, spans是512M, bitmap是16G.
这个方法虽然比较笨, 可是能够在任何状况下输出咱们想要的值.

此外, go运行时(runtime)的源代码会包括在目标文件中,
例如你对runtime.newobject下断点能够对go自身的源代码进行调试.

参考连接

https://golang.org
https://golang.org/doc/install/source
https://golang.org/doc/gdb
http://lldb.llvm.org/tutorial.html
http://legendtkl.com/archives

接下来我将分析golang的任务调度机制和三色GC的具体实现, 敬请期待.

 
分类:  Golang源码探索
相关文章
相关标签/搜索