Skip to content

Latest commit

 

History

History
75 lines (48 loc) · 2.97 KB

1.2 geth-以太坊网络启动的入口.md

File metadata and controls

75 lines (48 loc) · 2.97 KB

geth-以太坊网络启动的入口

一. geth守护进程

geth是go-ethereum中最重要的一个命令行工具,当启动geth守护进程,它将连接到网络中的以太坊节点,不断与其他节点进行通信,并下载同步区块数据。

另外,它还能验证并执行区块中的交易,同时将交易添加到区块链上。

它既充当服务器,又充当客户端。当geth作为服务器的时候,外部可以通过RPC调用暴露的API来执行各种操作。geth作为客户端,就是一个命令行工具,它可以连接到正在运行的节点,并执行各种操作,包括创建账户、管理账户、查询区块链、创建合约、交易转账等功能。

geth的区块链网络访问图如下:

image

二. gdb调试geth

前面只是对geth做了初步介绍,接下来将通过源码对geth做深度剖析。这里通过gdb调试的方式跟踪geth的启动、以及后续的运行流程。

这里假设你以及安装好了golang和go-ethereum,以及gdb调试工具。

go-ethereum目录结构如下:

$GOPATH/src
├── github.com
│   └── ethereum
│       └── go-ethereum
│           └──build
└── golang.org
    └── x
        └── net

启动geth并加载go语言gdb

gdb build/bin/geth
(gdb) source /usr/local/go/src/runtime/runtime-gdb.py
(gdb) info goroutines // 查看 goroutines 信息
(gdb)

断点调试

(gdb) b main.go:139   //init()函数
(gdb) b main.main     //main()函数
(gdb) b main.go:207   //geth()函数
(gdb) r

运行结果如下:

image

可以看到,geth进程是通过main.main()入口启动的。

其实,go语言里面有两个默认的函数,一个是main()函数,一个是init()函数。 go语言会自动按照一定的顺序先调用所有包的init()函数,然后才会调用main()函数。

在这里,go 程序首先通过 /usr/local/go/src/runtime/proc.go:106 的main入口函数启动geth, 然后会调用 geth/main.go里面的init()函数, 然后才会调用 ./go-ethereum/cmd/geth/main.go:197 的main()函数。

在调用init()函数的时候,首先初始化app.Commands,这个过程会调用./go-ethereum/cmd/geth/下的*cmd.go来完成变量的实例化。

接下来,进入到geth的main()函数,在main函数中,直接运行app.Run(os.Args)来完成启动。

然后调用 geth/main.go:207 里面的geth()函数, geth函数通过makeFullNode()创建并启动geth节点。

app.Run()函数的实现在go-ethereum/vendor/gopkg.in/urfave/cli.v1/app.go:175 中, urfave/cli是一个快速、简洁构造go命令行应用的工具库。

参考资料:

  1. Go语言debug调试
  2. Go实现命令行应用的工具cli