美文网首页区块链研习社
比特币源码阅读(三):初始化和启动(2)

比特币源码阅读(三):初始化和启动(2)

作者: 沙漠中的猴 | 来源:发表于2017-11-12 18:52 被阅读0次

    3. AppInit

    用于AppInit函数有点长,咱们把函数拆开一点一点的看,我将该函数分成了5个部分,并通过数字来标识当前函数代码块。

    // 1.
    // 函数AppInit()  位置:src/bitcoind.cpp
    
    boost::thread_group threadGroup;  //定义线程组,用来管理线程
    CScheduler scheduler;
       
    bool fRet = false;
    

    定义了一个线程组用来管理线程。CScheduler这个类声明在/src/scheduler.h。我们来看下CScheduler中的两个函数

    //类:CScheduler  文件位置:/src/scheduler.h
    
    // Convenience method: call f once deltaSeconds from now
    void scheduleFromNow(Function f, int64_t deltaSeconds);
    
    // Another convenience method: call f approximately
    // every deltaSeconds forever, starting deltaSeconds from now.
    // To be more precise: every time f is finished, it
    // is rescheduled to run deltaSeconds later. If you
    // need more accurate scheduling, don't use this method.
    void scheduleEvery(Function f, int64_t deltaSeconds);
    

    scheduleFromNow()作用是过一段时间执行Function fscheduleEvery()作用是每隔一段时间来执行Function f。可以单独新建线程来处理业务逻辑,不会干扰主线程。
    CScheduler的作用主要是用来管理后台任务

    // 2.
    //函数:AppInit() 位置:/src/bitcoind.cpp 
     
        gArgs.ParseParameters(argc, argv);
    
        // Process help and version before taking care about datadir
        if (IsArgSet("-?") || IsArgSet("-h") ||  IsArgSet("-help") || IsArgSet("-version"))
        {
            std::string strUsage = strprintf(_("%s Daemon"), _(PACKAGE_NAME)) + " " + _("version") + " " + FormatFullVersion() + "\n";
    
            if (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;
        }
    
    

    gArgs声明在/src/util.h类型是ArgsManager。函数ParseParameters(argc, argv)解析bitcoind命令行输入的参数,并存入map中。函数定义在/src/util.cpp

    上面的代码会将命令行参数为help或者version做显示处理。其他的命令忽略。

    // 3. 
       try
        {
            // 检查文件目录的有效性
            if (!boost::filesystem::is_directory(GetDataDir(false)))
            {
                fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str());
                return false;
            }
            try
            {
                // 读取配置文件
                ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME));
            } catch (const std::exception& e) {
                fprintf(stderr,"Error reading configuration file: %s\n", e.what());
                return false;
            }
            // 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;
            }
    

    检查数据目录的正确性,数据目录的位置可以通过-datadir来指定。文件目录主要存储了保存同步的区块信息,钱包信息,配置信息等等重要信息。

    默认的数据目录位置:
        Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
        Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
        Mac: ~/Library/Application Support/Bitcoin
        Unix: ~/.bitcoin
    

    然后读取配置文件,配置文件默认的名称是bitcoin.conf存储在数据目录文件夹下 ~/.bitcoin/bitcoin.conf 。也可以通过-conf命令来指定配置文件的位置。当然这个文件也可以不设置。

    // src/util.cpp   
    const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf";
    

    比特币网络主要有以下三种:

    • main 主网络,如果不设置参数,默认连接到主网络
    • testnet 测试网络,可以通过该网络来模拟主网络的操作,算力相对来说小一些。
    • regtest 私有网络,供开发者开发调试

    接下来通过ChainNameFromCommandLine函数来获取当前要连接到哪个网络,之后通过SelectParams函数来对该网络进行参数配置。

    // src/chainparams.cpp
    void SelectParams(const std::string& network)
    {
        SelectBaseParams(network);
        globalChainParams = CreateChainParams(network);
    }
    

    SelectBaseParams函数根据当前设置的网络来配置相应的RPC端口号。

    • 主网络:nRPCPort = 8332
    • 测试网络: nRPCPort = 18332
    • 私有网络:nRPCPort = 18332
      这些参数都分别存放在/src/chainparamsbase.cpp文件的CBaseMainParams、CBaseTestNetParams、CBaseRegTestParams这三个类中
      CreateChainParams 函数根据当前设置的网络来配置区块生成、共识参数、协议升级等重要参数。该参数的具体内容可以在/src/chainparams.cpp文件的CMainParams类查看。
    // 4. 
            // Error out when loose non-argument tokens are encountered on command line
            //判断命令行参数是否正确,取第一个参数,如果是WIN32系统可以使用'-'或者'/',其他系统则是'-'
            for (int i = 1; i < argc; i++) {
                if (!IsSwitchChar(argv[i][0])) {
                    fprintf(stderr, "Error: Command line contains unexpected token '%s', see bitcoind -h for a list of options.\n", argv[i]);
                    exit(EXIT_FAILURE);
                }
            }
    
    // 5.
     // -server defaults to true for bitcoind but not for the GUI so do this here
            gArgs.SoftSetBoolArg("-server", true);
            // Set this early so that parameter interactions go to console
            InitLogging();
            InitParameterInteraction();
            if (!AppInitBasicSetup())
            {
                // InitError will have been called with detailed error, which ends up on console
                exit(EXIT_FAILURE);
            }
            if (!AppInitParameterInteraction())
            {
                // InitError will have been called with detailed error, which ends up on console
                exit(EXIT_FAILURE);
            }
            if (!AppInitSanityChecks())
            {
                // InitError will have been called with detailed error, which ends up on console
                exit(EXIT_FAILURE);
            }
            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
            }
            // Lock data directory after daemonization
            if (!AppInitLockDataDirectory())
            {
                // If locking the data directory failed, exit immediately
                exit(EXIT_FAILURE);
            }
            fRet = AppInitMain(threadGroup, scheduler);
        }
        catch (const std::exception& e) {
            PrintExceptionContinue(&e, "AppInit()");
        } catch (...) {
            PrintExceptionContinue(nullptr, "AppInit()");
        }
    
        if (!fRet)
        {
            Interrupt(threadGroup);
            threadGroup.join_all();
        } else {
            WaitForShutdown(&threadGroup);
        }
        Shutdown();
    
        return fRet;
    }
    

    用于这段代码内容较多,所以在这里做一个简单的讲解。后续内容会做一个详细讲解。
    gArgs.SoftSetBoolArg("-server", true);-server参数设置为1。先判断该参数是否存在,如果存在返回false,不存在返回true。

    // src/util.cpp 
    
    // 如果-server存在,则返回false。不存在则返回true。
    bool ArgsManager::SoftSetArg(const std::string& strArg, const std::string& strValue)
    {
        LOCK(cs_args);
        if (mapArgs.count(strArg))
            return false;
        ForceSetArg(strArg, strValue);
        return true;
    }
    //当fValue设置为true时,将-server设置成1。否则设置为0。
    bool ArgsManager::SoftSetBoolArg(const std::string& strArg, bool fValue)
    {
        if (fValue)
            return SoftSetArg(strArg, std::string("1"));
        else
            return SoftSetArg(strArg, std::string("0"));
    }
    

    下面的函数大概作用为:

    1. InitLogging() 初始化日志系统
    2. InitParameterInteraction() 初始化网络参数规则
    3. AppInitBasicSetup() 设置消息格式及处理回调逻辑。
    4. AppInitParameterInteraction() 设置区块链运行参数
    5. AppInitSanityChecks() 对依赖库进行检查
    6. gArgs.GetBoolArg("-daemon", false)
    7. AppInitMain() 主程序初始化
    8. ShutDown() 关闭进程

    相关文章

      网友评论

        本文标题:比特币源码阅读(三):初始化和启动(2)

        本文链接:https://www.haomeiwen.com/subject/aamsextx.html