上次讲了src文件夹即比特币的源码所在目录,今天从程序入口,也就是main函数开始,比特币源码有好几个可执行程序,也就有好几个程序入口,我们从最重要的一个也就是src目录下的bitcoind.cpp下的main函数开始,这里注意是bitcoind.cpp不是bitcoin.cpp,在bitcoin后面多了一个d,而bitcoin.cpp是primitive文件夹下的其他文件,里面也有一个main函数,但不是我们要找的这个。
源码如下:
int main(int argc, char* argv[])
{
SetupEnvironment();
// Connect bitcoind signal handlers
noui_connect();
return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
}
SetupEnvironment();顾名思义,主要就是设置运行比特币节点需要的一些环境,其函数定义在util.cpp里,
源码如下:
void SetupEnvironment()
{
#ifdef HAVE_MALLOPT_ARENA_MAX
// 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 (POSIX是Unix的标准)systems (e.g. Linux, but not BSD(BSD (Berkeley Software Distribution,伯克利软件套件)是Unix的衍生系统)) the environment's locale
// may be invalid, in which case the "C" locale is used as fallback.//可能会不合法,在这种情况下,“C”语言环境用作后备。
#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);
}
它其实干了三件事:
第一部分:
if (sizeof(void*) == 4) {
mallopt(M_ARENA_MAX, 1);
}
这个地方是内存分配区设置,从代码看它先通过sizeof(void*)==4判断当前系统是否为32位,如果是就让系统按CPU进行自动设置,目的是为了防止32位操作系统中虚拟地址空间过渡使用。其实已经和区块链的实现无关了。这里不深究,知道它就是程序中的控制内存分配就行,不会影响后面的理解。
第二部分:
try {
std::locale(""); // Raises a runtime error if current locale is invalid(//如果当前区域设置无效,则引发运行时错误)
} catch (const std::runtime_error&) {
setenv("LC_ALL", "C", 1);
}
本地化设置,系统区域设置,就是国家或地区设置,将决定程序所使用的当前语言编码、日期格式、数字格式及其它与区域有关的设置,依然不重要,知道有这么个东西就行。
第三部分:
std::locale loc = fs::path::imbue(std::locale::classic());
fs::path::imbue(loc);
本地化文件路径设置,具体实现不用管,和区块链的实现一点关系都没有。
现在我们回到main函数里面下一句是noui_connect();
这个的定义在noui.cpp里
源码如下:
void noui_connect()
{
// Connect bitcoind signal handlers
uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox);
uiInterface.ThreadSafeQuestion.connect(noui_ThreadSafeQuestion);
uiInterface.InitMessage.connect(noui_InitMessage);
}
顾名思义,noui,没有UI(user interface用户界面)该文件实现是无操作界面的,noui_connect就是无界面情况下的信息连接,具体实现和区块链没关系,就跳过。
回到main函数里面下一句是
return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
也就是执行AppInit(argc, argv)如果为真就返回EXIT_SUCCESS,为假就返回EXIT_FAILURE
AppInit(argc, argv)是应用程序初始化,也就是整个比特币后台进程真正开始运行的入口。
所以重要的东西就是这个AppInit(argc, argv)里到底写了什么:
我们下篇文章讲。