>>> geth 可执行文件怎么构建出来的?
上篇文章中讲,我们是通过 make all 构建出所有可执行文件。那么它到底做了些什么呢?
make是一个构建工具,它依据指定规则来构建目标,而构建什么目标以及如何构建目标都写在了 makefile 文件中(当然你也可以不叫makefile)
推荐大家阅读这篇文章 http://www.ruanyifeng.com/blog/2015/02/make.html ,学习 makefile 文件的编写
可以看到以太坊源码根目录存在一个makefile文件,通过上面的学习应该知道了 make all 到底做了什么
GORUN = env GO111MODULE=on go run
...
all:
$(GORUN) build/ci.go install
make all执行的其实就是
env GO111MODULE=on go run build/ci.go install
意思是开启 golang 的 modules 特性,运行 build 文件夹下的 ci.go 文件,并传递参数 install
下面可以查看 ci.go 文件是如何运行的了。
首先找到 main 函数,往下开始分析代码。
传递的是install,所以找到 doInstall 函数
- 检查本机 golang 版本,如果版本不满足要求就直接退出,编译失败
- 检查指定的编译目标架构,如果未指定,默认是amd64,根据目标架构组装相应的命令选项以及参数
可以得到最终得到的编译命令是
go install -ldflags -X main.gitCommit=58cf5686eab9019cc01e202e846a6bbc70a3301d -X main.gitDate= -s -v ./...
就是编译根目录的所有包。
同理 make geth 最终的构建命令就是
go install -ldflags -X main.gitCommit=58cf5686eab9019cc01e202e846a6bbc70a3301d -X main.gitDate= -s -v ./cmd/geth
所以可以看出 ./cmd/geth 包就是 geth 的入口。我们就可以从这开始阅读源码了。
如果还有人不知道 go 可执行文件如何编译的,不知道go install的用法,可以网上学习,篇幅关系,这里不讲了。
>>> 节点是如何启动的?
现在从 cmd/geth/main.go 文件开始
- 通过 main 函数以及 init 函数对 geth 的各种参数以及选项进行配置,就是什么命令执行什么样的动作。如果没有指定子命令,默认执行 geth 函数中的代码。
上篇文章中的
./build/bin/geth --datadir=./private/ --mine --miner.threads=1 --etherbase=0x0000000000000000000000000000000000000003 --port 33303 --rpc --rpcport 8545 --rpcapi eth,web3,net,rpc,admin --ethash.dagdir ./private/tagdir/
就执行的是 geth 函数中的代码。接下来看 geth 函数
func geth(ctx *cli.Context) error {
if args := ctx.Args(); len(args) > 0 {
return fmt.Errorf("invalid command: %q", args[0])
}
prepare(ctx)
node := makeFullNode(ctx)
defer node.Close()
startNode(ctx, node)
node.Wait()
return nil
}
- 配置内存缓存限额(配置go gc的回收百分比),并安装运行时指标收集系统
- 准备构建一个全节点。首先会注册一个Eth服务(以太坊中每个模块都被称作为一个服务),Eth服务中,如果指定了使用轻量协议(--light.serve设置如果大于0就是使用了,默认是0),则会开启一个LES(以太坊客户端的轻量级的子协议)服务器提供服务。
- 如果启用了Whisper协议(--shh选项),则注册Whisper服务。
- 如果启用了GraphQL功能,则注册一个GraphQL服务。
- 如果启用了ethstats功能,则注册ethstats服务。
- 启动全节点
- 启动p2p服务器
- 依次启动前面注册过的所有服务
- 按需启动各种api端点服务器(HTTP、WS、RPC等)
- 开启一个协程拦截终止命令(SIGINT和SIGTERM),用于优雅关闭退出
- 解锁钱包账户(如果参数指定了的话),便于余额操作
- 设置新建钱包、开启钱包、关闭钱包事件的处理器
- 配置eth服务和les服务的与节点交互的rpc客户端
- 订阅同步完成的事件。处理--exitwhensynced选项,同步完成就退出节点
- 如果开启了挖矿,则启动挖矿
- 等待节点运行结束(关闭或异常退出)
有疑问加站长微信联系(非本文作者)