在第一講中,我們使用了which bitcoind和which bitcoin-cli兩個命令來驗證比特幣客戶端是否安裝成功。那么我們就可以猜測會有個程序入口與bitcoind相關(guān)。
果不其然,在src目錄下有個bitcoind.cpp文件。

從該文件中可以找到程序入口的main函數(shù)。
int main(int argc, char* argv[])
{
SetupEnvironment();
// Connect bitcoind signal handlers
noui_connect();
return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
}
這一小節(jié)主要講解SetupEnvironment(), 該函數(shù)是在src/util.cpp文件中定義的函數(shù)。
其作用有以下三個方面:

1.內(nèi)存分配區(qū)設(shè)置
#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);
}
這里判斷如果是32位系統(tǒng)(sizeof(void*) == 4),即只分配一個arena內(nèi)存區(qū),防止虛擬地址空間過度使用。自從glibc 2.10版本后,針對每個核心,C標(biāo)準(zhǔn)庫都會默認(rèn)創(chuàng)建兩個堆內(nèi)存區(qū)。這是公認(rèn)會導(dǎo)致內(nèi)存地址空間過度使用的問題。
科普:arena:可以理解為一個較大且連續(xù)的內(nèi)存分配區(qū),需要手動來管理。
2.本地化設(shè)置
#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);
}
在大部分POSIX系統(tǒng)(比如Linux,但非BSD),環(huán)境的locale即系統(tǒng)區(qū)域設(shè)置可能會無效,假如當(dāng)前的本地化設(shè)置無效,將拋出該運行時異常,同時在捕獲后將該值設(shè)置為“C”。
Tips:
?locale決定當(dāng)前程序所使用的語言編碼、日期格式、數(shù)字格式及其它與區(qū)域有關(guān)的設(shè)置,詳情參考:http://blog.csdn.net/haiross/article/details/45074355
C:缺省值:ANSI-C conventions,C語言標(biāo)準(zhǔn)規(guī)范、約定。比如函數(shù)命名規(guī)范等,由美國國家標(biāo)準(zhǔn)學(xué)會發(fā)布。
POSIX:The Portable Operating System Interface。便攜式操作系統(tǒng)接口(POSIX)是由IEEE計算機學(xué)會指定的用于維護操作系統(tǒng)之間的兼容性的一系列標(biāo)準(zhǔn)。
關(guān)于函數(shù)setenv(const char *name, const char *value, int overwrite),作用是修改或增加一個環(huán)境變量,詳情參考https://linux.die.net/man/3/setenv
3.本地化文件路徑設(shè)置
#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);
路徑區(qū)域設(shè)置是采用懶初始化,即延遲初始化的方式,并且可以避免多線程環(huán)境下的析構(gòu)過程錯誤,通過主線程來顯式設(shè)置。一個dummy locale可以用來提取fs::path使用的內(nèi)部默認(rèn)locale(路徑),然后就可以顯式設(shè)置該路徑。
imbue:該函數(shù)將要設(shè)置的loc值與流和該流相關(guān)的流緩沖區(qū)(如果有的話)關(guān)聯(lián)起來,作為新的系統(tǒng)區(qū)域設(shè)置對象。詳情參考:http://www.cplusplus.com/reference/ios/ios/imbue/
這里設(shè)置的是文件系統(tǒng)路徑的本地化。
下一小節(jié)將講解比特幣源碼是如何處理信號連接的。
區(qū)塊鏈研習(xí)社源碼研讀班 Jacky