比特币源码分析(三) - 主程序初始化

本文是以一个整体的角度分析程序初始化过程中所做的操作,整个初始化过程如果要分开来细讲可以写好几篇,后面可能会根据实际情况具体展开分析。

主程序的入口函数main()在bitcoind.cpp文件中:

int main(int argc, char* argv[])
{
    SetupEnvironment();

    // Connect bitcoind signal handlers
    noui_connect();

    return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
}

一步一步分析下。
一、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);

2.处理查询帮助信息和版本信息的命令

    // Process help and version before taking care about datadir
    if (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;
    }

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;
        }

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;
        }

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;
        }

6.设置server标识为true,即启用RPC服务

        // -server defaults to true for bitcoind but not for the GUI so do this here
        gArgs.SoftSetBoolArg("-server", true);

7.初始化日志

        // Set this early so that parameter interactions go to console
        InitLogging();       

8.初始化参数交互,即根据规则将一些设置的参数转化为设置其他参数

       InitParameterInteraction();

8.建立Bitcoin Core的基础上下文环境

        if (!AppInitBasicSetup())
        {
            // InitError will have been called with detailed error, which ends up on console
            return false;
        }

9.初始化参数交互,根据设置的参数做一些逻辑条件判断,根据情况显示相应的警告信息或者异常信息,也会有相关计算,将结果存储在内部变量中

        if (!AppInitParameterInteraction())
        {
            // InitError will have been called with detailed error, which ends up on console
            return false;
        }

10.完整性检查

        if (!AppInitSanityChecks())
        {
            // InitError will have been called with detailed error, which ends up on console
            return false;
        }

11.判断是否需要在后台运行(Daemonize)

        if (gArgs.GetBoolArg("-daemon", false))
        {
            #if HAVE_DECL_DAEMON
            fprintf(stdout, "Bitcoin server starting\n");

            // Daemonize
            if (daemon(1, 0)) { // don't chdir (1), do close FDs (0)
                fprintf(stderr, "Error: daemon() failed: %s\n", strerror(errno));
                return false;
            }
            #else
            fprintf(stderr, "Error: -daemon is not supported on this operating system\n");
            return false;
            #endif // HAVE_DECL_DAEMON
        }       

12.锁住Bitcoin Core数据目录

        // Lock data directory after daemonization
        if (!AppInitLockDataDirectory())
        {
            // If locking the data directory failed, exit immediately
            return false;
        }

13.Bitcoin Core的主要初始化工作

        fRet = AppInitMain();

14.监结束程序的请求,若有结束程序的请求,则完成结束程序的相关操作

    if (!fRet)
    {
        Interrupt();
    } else {
        WaitForShutdown();
    }
    Shutdown();

猜你喜欢

转载自blog.csdn.net/yzpbright/article/details/81165546