00 摘要

bitcoin源码编译成功,将生成可执行文件:

  • bench_bitcoin: 作用是编译系统更新,主要检查系统使用的一些加密算法是否有新的更新。
          
    
  • bitcoin-cli: Bitcoind的一个功能完备的RPC客户端
    
  • bitcoind: 比特币核心执行程序,俗称bitcoin-core。
    
  • bitcoin-qt: 比特币钱包
    
  • bitcoin-tx: 比特币交易处理模块,支持交易的查询和创建。
    
  • test_bitcoin: 运行各个模块的测试代码。
    
  • test_bitcoin-qt: 运行钱包模块的测试代码。
    

01 Main

首先寻找bitcoind的main函数。直接找到src/bitcoind.cpp;

1
2
3
4
5
6
7
8
int main(int argc, char* argv[])
{
SetupEnvironment();//环境配置
// Connect bitcoind signal handlers 连接bitcoind信号处理机制
noui_connect();
return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
}

02 setEnvironment

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
void SetupEnvironment()
{
#ifdef HAVE_MALLOPT_ARENA_MAX
//判断计算机系统位数,32位系统创建一个堆内存,默认创建2
// glibc-specific: On 32-bit systems set the number of arenas to 1.
// By default, since glibc 2.10, the C library will create up to two heap
// arenas per core. This is known to cause excessive virtual address space
// usage in our usage. Work around it by setting the maximum number of
// arenas to 1.
if (sizeof(void*) == 4) {
mallopt(M_ARENA_MAX, 1);
}
#endif
// On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
// may be invalid, in which case the "C" locale is used as fallback.
#if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
try {
std::locale(""); // Raises a runtime error if current locale is invalid
} catch (const std::runtime_error&) {
setenv("LC_ALL", "C", 1);
}
#endif
// The path locale is lazy initialized and to avoid deinitialization errors
// in multithreading environments, it is set explicitly by the main thread.
// A dummy locale is used to extract the internal default locale, used by
// fs::path, which is then used to explicitly imbue the path.
std::locale loc = fs::path::imbue(std::locale::classic());
fs::path::imbue(loc);
}

函数首先通过:

1
sizeof(void*) == 4//判断当前系统是否是32位

如果是64位的话那么sizeof(void*)值就为8。
mallopt函数是用来控制malloc内存分配时的行为的(具体请参考http://man7.org/linux/man-pages/man3/mallopt.3.html),
M_ARENA_MAX参数是值最多能创建的arena数,一个arena是指malloc在分内内存时的一个内存池,而这个arena是线程安全的,也就是说多线程访问时是互斥访问的,既然是互斥访问的,那么很明显,当arena数量越多时,线程的竞争就越小,但是需要的内存也就越多(因为arena就相当于一次性申请大量内存,然后在malloc时慢慢分配出去)。

通过代码中的注释,我们发现glibc库会为每个核创建2个arena,而这会对32为系统造成虚拟地址空间不足的问题,所以这里设为1.

locale()是设置系统区域,这将决定程序所使用的当前语言编码、日期格式、数字格式及其它与区域有关的设置。

最后两行是文件路径的本地化设置,主要设计宽字符(Wide char)和多字节(Multi bytes)之间的转换问题。

1
2
3
4
5
6
7
void noui_connect()
{
// Connect bitcoind signal handlers
uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox);
uiInterface.ThreadSafeQuestion.connect(noui_ThreadSafeQuestion);
uiInterface.InitMessage.connect(noui_InitMessage);
}

CClientUIInterface类中定义了一些信号,其中三个分别是ThreadSafeMessageBox,ThreadSafeQuestion和InitMessage。再看前面的noui_connect中的变量,我们发现通过connect连接的插槽函数定义和信号中的定义完全一致,所以当信号触发的时候,这些连接的函数都会被调用。