本文主要是介绍主程序初始化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
比特币源码分析(三) - 主程序初始化
https://blog.csdn.net/yzpbright/article/details/81165546
本文是以一个整体的角度分析程序初始化过程中所做的操作,整个初始化过程如果要分开来细讲可以写好几篇,后面一系列文章会具体展开分析关键逻辑的源码。
主程序的入口函数main()在bitcoind.cpp文件中:
int main(int argc, char* argv[])
{SetupEnvironment();// Connect bitcoind signal handlersnoui_connect();return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
一步一步分析下。
一、SetupEnvironment() ,设置运行环境
二、noui_connect(),连接bitcoind信号处理器
三、AppInit(argc, argv), 应用初始化,这里有大量的初始化操作,接下来一步一步分析下这个函数的源码:
1.解析运行输入的参数,保存在 mapArgs 这个map容器中
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()gArgs.ParseParameters(argc, argv);
- 1
- 2
2.处理查询帮助信息和版本信息的命令
// Process help and version before taking care about datadirif (gArgs.IsArgSet("-?") || gArgs.IsArgSet("-h") || gArgs.IsArgSet("-help") || gArgs.IsArgSet("-version")){std::string strUsage = strprintf(_("%s Daemon"), _(PACKAGE_NAME)) + " " + _("version") + " " + FormatFullVersion() + "\n";if (gArgs.IsArgSet("-version")){strUsage += FormatParagraph(LicenseInfo());}else{strUsage += "\n" + _("Usage:") + "\n" +" bitcoind [options] " + strprintf(_("Start %s Daemon"), _(PACKAGE_NAME)) + "\n";strUsage += "\n" + HelpMessage(HMM_BITCOIND);}fprintf(stdout, "%s", strUsage.c_str());return true;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
3.检查应用的数据目录
if (!fs::is_directory(GetDataDir(false))){fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());return false;}
- 1
- 2
- 3
- 4
- 5
4.读取配置文件
try{gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));} catch (const std::exception& e) {fprintf(stderr,"Error reading configuration file: %s\n", e.what());return false;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
5.检查判断是主网还是测试网络,并设置区块链的全局参数
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)try {SelectParams(ChainNameFromCommandLine());} catch (const std::exception& e) {fprintf(stderr, "Error: %s\n", e.what());return false;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
6.设置server标识为true,即启用RPC服务
// -server defaults to true for bitcoind but not for the GUI so do this heregArgs.SoftSetBoolArg("-server", true);
- 1
- 2
7.初始化日志
// Set this early so that parameter interactions go to consoleInitLogging();
- 1
- 2
8.初始化参数交互,即根据规则将一些设置的参数转化为设置其他参数
InitParameterInteraction();
- 1
8.建立Bitcoin Core的基础上下文环境
if (!AppInitBasicSetup()){// InitError will have been called with detailed error, which ends up on consolereturn false;}
- 1
- 2
- 3
- 4
- 5
9.初始化参数交互,根据设置的参数做一些逻辑条件判断,根据情况显示相应的警告信息或者异常信息,也会有相关计算,将结果存储在内部变量中
if (!AppInitParameterInteraction()){// InitError will have been called with detailed error, which ends up on consolereturn false;}
- 1
- 2
- 3
- 4
- 5
10.完整性检查
if (!AppInitSanityChecks()){// InitError will have been called with detailed error, which ends up on consolereturn false;}
- 1
- 2
- 3
- 4
- 5
11.判断是否需要在后台运行(Daemonize)
if (gArgs.GetBoolArg("-daemon", false)){#if HAVE_DECL_DAEMONfprintf(stdout, "Bitcoin server starting\n");// Daemonizeif (daemon(1, 0)) { // don't chdir (1), do close FDs (0)fprintf(stderr, "Error: daemon() failed: %s\n", strerror(errno));return false;}#elsefprintf(stderr, "Error: -daemon is not supported on this operating system\n");return false;#endif // HAVE_DECL_DAEMON}
12.锁住Bitcoin Core数据目录
// Lock data directory after daemonizationif (!AppInitLockDataDirectory()){// If locking the data directory failed, exit immediatelyreturn false;}
13.Bitcoin Core的主要初始化工作
fRet = AppInitMain();
- 1
14.监结束程序的请求,若有结束程序的请求,则完成结束程序的相关操作
if (!fRet){Interrupt();} else {WaitForShutdown();}Shutdown();
P2P网络相关
CConnman
该类在src/net.h中声明,在src/net.cpp中实现。
class CConnman
{
public:
enum NumConnections {
CONNECTIONS_NONE = 0,
CONNECTIONS_IN = (1U << 0),
CONNECTIONS_OUT = (1U << 1),
CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT),
};
struct Options
{
ServiceFlags nLocalServices = NODE_NONE;
int nMaxConnections = 0;
int nMaxOutbound = 0;
int nMaxAddnode = 0;
int nMaxFeeler = 0;
int nBestHeight = 0;
CClientUIInterface* uiInterface = nullptr;
NetEventsInterface* m_msgproc = nullptr;
unsigned int nSendBufferMaxSize = 0;
unsigned int nReceiveFloodSize = 0;
uint64_t nMaxOutboundTimeframe = 0;
uint64_t nMaxOutboundLimit = 0;
std::vector<std::string> vSeedNodes;
std::vector<CSubNet> vWhitelistedRange;
std::vector<CService> vBinds, vWhiteBinds;
bool m_use_addrman_outgoing = true;
std::vector<std::string> m_specified_outgoing;
std::vector<std::string> m_added_nodes;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
该类是网络连接管理类,比较庞大,负责节点的启动、结束,推送消息,接收其他节点的连接等。
PeerLogicValidation
该类多重继承了两个接口类:CValidationInterface, 和 NetEventsInterface 。
CValidationInterface,主要是通知交易和区块相关的状态的改变。
NetEventsInterface,主要是处理从其他节点接收到的消息,发送消息,
/**
* Interface for message handling
*/
class NetEventsInterface
{
public:
virtual bool ProcessMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
virtual bool SendMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
virtual void InitializeNode(CNode* pnode) = 0;
virtual void FinalizeNode(NodeId id, bool& update_connection_time) = 0;
};
1
2
3
4
5
6
7
8
9
10
11
除此之外,该类新增了几个方法,用于处理过期信息和剔除多余的对等节点
void ConsiderEviction(CNode *pto, int64_t time_in_seconds);
void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams);
void EvictExtraOutboundPeers(int64_t time_in_seconds);
这篇关于主程序初始化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!