初始化和启动模块(1)
一、找代码入口
代码的入口在/src/文件下的bitcoin.cpp文件中的188行,如图所示:
二、逻辑关系
这个main()函数只有简单的3行有效代码,它的逻辑关系如下图所示:
接下来我们对这三个函数更加详细的解读。
Ⅰ:SetupEnvironment()函数解读
SetupEnvironment()函数主要是实现比特币的后台进程运行环境的设置,函数的定义在src/util.cpp中,位于第836行。该函数的组成如下图所示:
(1)内存分配区设置
此处内存分配区设置的目的是为了防止32位操作系统中虚拟地址空间过度使用,即程序中的控制内存分配。通过sizeof(void*)==4判断当前系统是否为32位(如果是64位的话那么sizeof(void*)值就为8)。如果是,则通过mallopt()设置只有1个内存分配区。
mallopt()函数是用来控制malloc内存分配时的行为的,而M_ARENA_MAX参数是值最多能创建的arena数,一个arena是指malloc在分配内存时的一个内存池,而这个arena是线程安全的,也就是说多线程访问时是互斥访问的;既然是互斥访问的,那么很明显,当arena数量越多时,线程的竞争就越小,但是需要的内存也就越多(因为arena就相当于一次性申请大量内存,然后在malloc分配内存时慢慢的分配出去)。通过代码中的注释,我们发现glibc库会为每个核创建2个arena,而这会对32位系统造成虚拟地址空间不足的问题,所以对于32位系统要设置为1。
(2)本地化设置
C/C++程序中,locale(即系统区域设置,即国家或地区设置)将决定程序所使用的当前语言编码、日期格式、数字格式及其它与区域有关的设置,locale设置的正确与否将影响到程序中字符串处理(wchar_t如何输出、strftime()的格式等)。因此,对于每一个程序,都应该慎重处理locale设置。
(3)本地化文件路径设置
第三部分代码主要通过boost::filesystem::path::imbue实现文件系统的本地化设置。主要涉及宽字符(Wide char)和多字节(Multi bytes)之间的转换问题。路径区域设置是惰性初始化的,为了避免多线程环境中的初始化错误,它是由主线程显式设置的。虚拟语言环境用于提取fs::path使用的内部默认语言环境,然后使用该语言环境显式地填充路径。
Ⅱ:noui_connect()函数解读
noui_connect()函数实现的是无界面情况下连接bitcoind信息处理程序,它在src/noui.cpp文件的第52行定义了。下图为它的函数主体:
其中三个函数的的形式类似,现在以第一个为例介绍代码含义:
uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox);
(1)uiInterface为全局变量,它在ui_interface.h的第123行被声明:
在ui_interface.cpp的第8行被定义:
(2)ThreadSafeMessageBox、ThreadSafeQuestion和InitMessage变量位于ui_interface.h的第74-81行。其代码内容如下图:
代码中对于这三个变量的作用解释分别为:
ThreadSafeMessageBox:显示消息框。
ThreadSafeQuestion:如果可以,问用户一个问题。否则返回 ThreadSafeMessageBox(非交互式消息、标题、样式)并返回false。
InitMessage:在初始化期间的进展消息。
(3)我们也能看到这3个变量的类型都是:boost::signals2::signal类型,这个是信号/槽机制,至于关于这个机制的详细讲解请参考下面的链接:
(4)而noui_ThreadSafeMessageBox槽函数的实现就在noui.cpp的第15行中定义。如图所示:
(5)该函数中完成了显示消息框信号的实现。其主要通过日志打印和文件记录方式实现相应信号的处理,以作为程序运行过程的记录。
总结:
noui_connect()函数实现的是无界面情况下连接bitcoind信息处理程序,该处理程序会显示消息框,通过日志打印和文件记录方式记录非交互式消息、标题、样式和在初始化期间的进展消息。