Bitcoin Core 0.11 (ch 3): Initialization and Startup
このページでは、起動と初期化を管理するBitcoin Coreコードについて説明します。
プログラムエントリポイント
プログラムのエントリポイントは bitcoind.cpp にあります。
main()はコードの3行です:
- SetupEnvironment()(これはプログラムのロケールを設定します)
- 信号ハンドラを接続する
- AppInit()(この関数はプログラムの寿命を延ばす)
AppInit:これは bitcoind.cpp の近くにあります。
- コマンドラインを解析する
- データディレクトリを開きます。
- 設定ファイルを読み込みます
- プロセスをフォークします(デーモンとして実行している場合)
- コントロールを init.cpp にあるAppInit2()に渡します。
初期化ステップ( init.cpp )
AppInit2()はビットコインシステムを初期化します。
これには約800行のコードが含まれており、12段階に分かれています。
各ステップが始まる場所は、コードに文書化されています。 Init.cpp にはファイルの先頭にいくつかの関数がありますが、大部分はAppInit2()で構成されています。
次の表は、手順をまとめたものです。
初期化 ステップ |
簡単な説明 | 詳細 |
---|---|---|
1 | OS固有のセットアップタスク | これらの作業は特に興味深いものではありません。 詳細は、コードを参照してください。 |
2 | パラメータの相互作用 | 特定のコマンドラインオプションでは、特定の方法で他のオプションを設定する必要があります。 たとえば、-zapwallettxesは-rescanを意味します。したがって、コードは-rescanフラグ= trueを設定します(まだ存在していない場合)。 |
3 | 内部フラグ / パラメータ健全性チェック |
特定のパラメータのグローバル変数を設定します。 財布については、取引料金レベルを正当性をチェックします(あなたの手数料がリレー[エラー]の資格を得るのに十分高いが、不当に高い[警告]ではないことを確認します)。 |
4 | アプリケーション初期化。 / RPCサーバー |
データディレクトリをロックします。 (できない場合は、エラーを出力して終了してください。) |
5 | ウォレット・データベースの整合性の確認 | ウォレットが有効になっている場合は、開こうとします。 ウォレットが破損していることがわかっている場合(-salvagewallet)、パスワードの回復を試みます。 |
6 | ネットワーク初期化 |
ノードは特定の信号を登録する。 |
7 | ブロックチェーンをロードします。 |
ブロックチェーンをメモリにロードし、UTXOキャッシュを初期化します。 |
8 | ウォレットをロードします。 | プログラムが初めて実行された場合は、ウォレットが作成され、最初のキー(アドレス)が与えられます。 |
9 | Datadirのメンテナンス | ユーザーがブロックプルーニングを行っている場合は、NODE_NETWORKの設定を解除し、プルーニング機能を呼び出します。 |
10 | インポートブロック | 現在有効なチェーンとして接続されていないブロックチェーンデータベースのチェーンをスキャンします。 |
11 | 開始ノード / RPCサーバー |
net.cppでStartNodeを呼び出します。 |
12 | 終了 |
AppInit2が終了すると、 bitcoind.cpp のAppInit()に戻ります。
そこで、コードのトップレベルスレッドは、WaitForShutdown()という関数で無期限にループします。 2秒間スリープ状態になり、ユーザーがctrl-Cを押したかどうかを確認します。 その場合は、 init.cpp でShutdown()を呼び出します。
シャットダウン()は、RPCサーバーをシャットダウンし、ノードを停止し、シグナルハンドラの登録を解除し、プログラムが完了します。
キャッシュサイズ
ステップ7は、キャッシュサイズを初期化した。手順7で考えられる3つのキャッシュがあります.2つはLevelDBデータベースキャッシュであり、もう1つはコインキャッシュであり、そのサイズは main.cpp のフラッシュコードによって管理されます。
ユーザーは、-dbcacheを使用して合計キャッシュ・サイズを割り当てることができます。ユーザーは、特定の各キャッシュに割り当てるスペースを選択して選択することはできません。デフォルトの合計キャッシュサイズ= 100MB(最大:4GB、最小:4MB)。
'1)ブロックインデックスキャッシュ'
このキャッシュには、/ block / index LevelDBデータの圧縮されていないチャンクが保存され、LevelDBのドキュメントに記載されているように、LevelDBによって管理されます。 br>
ユーザーが完全なトランザクションインデックス(-txindex = 1)を有効にした場合、合計キャッシュサイズの1/8までになります。 -txindexが有効でない場合は、2 MiBだけが必要です。
'2)UTXOデータベースキャッシュ'
これは、/ chainstateデータベースのLevelDBキャッシュです。
このキャッシュは、合計キャッシュ・サイズに応じて、残りのキャッシュ・スペースの25〜50%に割り振られます。
'3)UTXOインメモリキャッシュ'
これは main.cpp コードで管理されるコインキャッシュです。 (FlushStateToDiskおよび関連する関数を参照)
変数(nCoinsCache)は、 main.h のexternとして宣言されています。 main.cpp には、5000 * 300にハードコードされています(メモリ内コインは約300バイトなので5000コインを意味します)。しかし、ステップ7で再初期化する必要があります。
このキャッシュには残りのキャッシュ領域がすべて与えられます。
このキャッシュは、初期化中にロードされるのではなく、コインがアクセスされるときに満たされます。 (これは、cachedCoinsUsage = 0を設定するCCoinsViewCacheコンストラクタによって検証できます)。
スレッド起動
このコードでは、boost :: thread_groupsを使用してさまざまなスレッドを管理しています。
Bitcoin Coreはマルチスレッドプログラムですが、 "参照Satoshiクライアントは主にシングルスレッドです"ということに注意してください。 BIP 31(2012)のMike Hearnによるコメント
つまり、プログラムの活動の大部分がメッセージングスレッド(ThreadMessageHandler - 以下を参照)で行われるということです。
ほとんどすべてのスレッドは、プログラムの起動時にスタック上に作成される単一のマスタースレッドグループの一部です( bitcoind.cpp を参照)。このスレッドグループはいくつかの子スレッドを生成する init.cpp に渡されます(いくつかのスクリプト検査スレッドを含みますが、これらはすべて別個のグループではなくマスタースレッドグループの一部です)。
スレッドグループは net.cpp に渡され、メッセージ処理スレッドを含むネットワーキングスレッドが作成されます。
2つの他のスレッドグループはタスク固有です。
- rpcサーバースレッドグループ(<r> rpcserver.h / cpp </u>を参照)
- minerスレッドグループ
当然のことながら、ノードはRPCサーバーがアクティブになっている場合にのみRPCサーバースレッドグループを作成し、マイナースレッドグループがマイニングの場合にのみ作成します。両方が無効の場合、Bitcoin Coreは単一のスレッドグループしか持たない。
'子スレッド'
親スレッド(プログラムが動作を開始するスレッドを意味する)は、ほとんどすべてのプログラムの作業を子スレッドに委譲します。 init.cpp と net.cpp でスレッドを生成した後、親スレッドは単にシャットダウンコマンドを待ちます。スレッドグループを開き、シャットダウンを続行します。
子スレッドは、作成された順にリストされています。
スレッド | いつ / どこで作成されました | 説明 |
---|---|---|
スクリプトチェック | ステップ4 init.cpp |
これはスレッドのセットで、デフォルトでは4です。 スクリプトチェック(署名チェックを含む)は高価なので、別のスレッドで処理されます。 |
スケジューラ | ステップ4 init.cpp |
スケジューラスレッド。 (TODO: describe) |
RPCスレッド | ステップ4 rpcserver.cpp |
RPCサーバーが有効な場合は、RPC呼び出しを処理するスレッドのグループを開始します。 |
インポート | ステップ10 init.cpp |
ブロックをインポートします。 3つのシナリオ: 1)再インデックス(blk ??? datファイルからすべての既知のブロックを再スキャンする)。 2)ブートストラップ(bootstrap.datをネットワークからの完全なIBDの代わりに使用します)。 3)-loadblock(特定のblk ???。datファイルをスキャンする) - これらのどれも適用されない場合、このスレッドは何もしません。 |
DNSアドレスシード | ステップ11 net.cpp |
dnsシードに基づいてIPアドレスのベクトルを構築しようとし、ベクトルとスレッドを終了します。 2014年6月のテストでは、これには約4秒かかり、158のアドレスが見つかりました。 |
プラグ&プレイ | ステップ11 net.cpp |
UPNP(ユニバーサルプラグ&プレイ) UPNPのポートマッピングを扱う。 |
SocketHandler | ステップ11 net.cpp |
このスレッドはソケットをサービスします: 関連するすべてのソケットのI / Oを50msのタイムアウトで待機します。 リスニングソケットで新しい着信接続を処理し、新しいピアのCNodeを作成します。 データストリームを受信して送信します。 何もしなかったソケットを切断状態に設定します。 |
OpenAddedConnections | ステップ11 net.cpp |
-addnodeパラメーターを使用して、ユーザーが指定したアウトバウンド接続を開始します。 接続できない場合、各サイクルで2分間スリープします。 |
OpenConnections | ステップ11 net.cpp |
DNSシードから他のアウトバウンド接続を開始する(失敗した場合、固定シードに基づいてノードを見つける) 接続できない場合、各サイクルで500ミリ秒間スリープします。 |
MessageHandler | ステップ11 net.cpp |
これがプログラムの主なスレッドです。 このスレッドはwhile(true)ループを実行し、メッセージの送受信を行います。 (参照 net.cpp:1049) このコードでは、boost :: signals2を使用してmain.cppのProcessMessages関数とSendMessages関数を呼び出します。 (シグナルを導入するコードはPR 2154にあります - そのプルで最後から2番目のコミットを参照してください)。 ProcessMessageとSendMessageはこのスレッドで実行されます。 したがって、 main.cpp のコードのほとんどはこのスレッドで実行されます。 |
ウォレットフリュッシャー | ステップ12 init.cpp |
ウォレットが有効な場合、このスレッドは定期的にウォレットをフラッシュします。 |
関連項目
Core 0.11(Ch 1):概要
Bitcoin Core 0.11(Ch 2):データストレージ
Bitcoin Core 0.11(Ch 4):P2Pネットワーク
Bitcoin Core 0.11(Ch 5):初期ブロックダウンロード
Bitcoin Core 0.11(Ch 6):ブロックチェーン