主程序的入口函数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() 源码。
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) {//如果是32位系统,就将内存池数目设置为1个,默认是2个,避免导致使用过多的虚拟地址空间
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);//本地化文件路径设置
}
内存池设置
glibc库默认会创建2个arena,而这会对32为系统造成虚拟地址空间不足的问题,所以判断若是32位系统,就将内存池数目设置为1个。mallopt函数是用来控制malloc内存分配时的行为的(具体请参考http://man7.org/linux/man-pages/man3/mallopt.3.html),而M_ARENA_MAX参数是指最多能创建的arena数,一个arena是指malloc在分配内存时的一个内存池。
区域设置
locale()方法是设置系统区域,即国家或地区设置,决定程序所使用的当前语言编码、日期格式、数字格式及其它与区域有关的设置,locale将影响到程序中字符串处理(wchar_t如何输出、strftime()的格式等)。
本地化文件路径设置
boost::filesystem::path::imbue()方法是文件系统的本地化设置。主要涉及宽字符(Wide char)和多字节(Multi bytes)之间的转换问题。
void noui_connect()
{
// Connect bitcoind signal handlers
uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox);
uiInterface.ThreadSafeQuestion.connect(noui_ThreadSafeQuestion);
uiInterface.InitMessage.connect(noui_InitMessage);
}
该方法实现无界面情况下连接bitcoind信息处理程序,ThreadSafeMessageBox,ThreadSafeQuestion,InitMessage这三个变量声明在src/ui_interface.h文件中,都是boost::signals2::signal类型。这里涉及到Boost信号/槽机制。看下槽函数noui_ThreadSafeMessageBox:
static bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
{
bool fSecure = style & CClientUIInterface::SECURE;
style &= ~CClientUIInterface::SECURE;
std::string strCaption;
// Check for usage of predefined caption
switch (style) {
case CClientUIInterface::MSG_ERROR:
strCaption += _("Error");
break;
case CClientUIInterface::MSG_WARNING:
strCaption += _("Warning");
break;
case CClientUIInterface::MSG_INFORMATION:
strCaption += _("Information");
break;
default:
strCaption += caption; // Use supplied caption (can be empty)
}
if (!fSecure)
LogPrintf("%s: %s\n", strCaption, message);
fprintf(stderr, "%s: %s\n", strCaption.c_str(), message.c_str());
return false;
}
该函数将相应的消息输出到日志中,同时也输出到标准异常输出设备中。