EOS 程式碼分析 [1] —— AppBase
ofollow,noindex">EOSIO/appbase ,如專案介紹所說——
The AppBase library provides a basic framework for building applications from a set of plugins. AppBase manages the plugin life-cycle and ensures that all plugins are configured, initialized, started, and shutdown in the proper order.
是一個從一系列外掛構建應用的基本框架。 EOS的大多應用都是基於這個框架來構建的。
AppBase是獨立於EOS專案的一個獨立專案,可以單獨的編譯,我們也可以利用這個框架構建自己的應用。
為了方便描述,我fork了一份程式碼,並在這個fork專案上添加了我閱讀過程中的註釋,這個fork的專案在這裡:
下文的介紹均基於AppBase提供的示例程式
為基礎進行說明,這個示例程式實現了一個
net_plugin
,這個
net_plugin
又有一個依賴項
chain_plugin
。這基本展示了AppBase使用中的方方面面。
0. 基本使用流程
一個基於AppBase的程式的基本使用流程如下:
-
註冊外掛,
register_plugin
-
初始化,
initialize
-
啟動,
startup
-
進入事件監聽等待,
exec
-
程式退出,
shutdown
。
基本上就是這麼簡單,AppBase本身提供了一個基礎程序環境,來使得使用者的程式碼可以以外掛的形式整合進來。
下面我們逐一解析一下這些步驟
1. 註冊外掛
application::register_plugin
是一個模板函式,模板引數是要註冊的外掛的型別。
該函式首先通過外掛的名稱查詢該外掛是否已經註冊過,如果註冊過則直接返回,不會重複註冊。外掛名的名稱是根據外掛的型別推導得來的。
如果沒有註冊過,則new
一個外掛的物件,並將其記錄進plugins
這個列表中。
呼叫外掛自身的register_dependencies
來註冊外掛自身的依賴,外掛的依賴也是外掛。
2. 初始化
從
application::initialize
函式的實現可以看到實際的初始化工作是在application::initialize_impl
完成的。
其完成的主要工作是完成程式配置項的設定和根據配置項做初始化。
配置項的初始化部分,首先是呼叫外掛的配置項設定
,然後才是程式自身的配置項設定
。配置項的處理是使用boost::program_options
完成的。
配置項處理完成後,首先是
根據配置進行application
自身的初始化處理
,然後是根據配置項進行外掛的初始化處理
。
3. 啟動
application::startup
的過程很簡單,就是逐一呼叫外掛的
startup
函式,並處理異常。
因為
application::startup
本身不進行任何應用邏輯的處理,所有的應用邏輯都是外掛來完成的,所以我們只要看一下外掛是如何完成
startup
的。
我們發現,使用者並不需要實現startup
函式,而是實現一個
plugin_requires
和
plugin_startup
。而事實上如果我們觀察示例程式,發現其並沒有實現plugin_requires
函式,這個函式事實上是實現了的,由一個
APPBASE_PLUGIN_REQUIRES
巨集來實現,這個巨集極大的簡化了宣告依賴的過程,只需要提供一個依賴的外掛的型別的列表即可,我的程式碼註釋中有對這個巨集的簡單解釋
,你也可是嘗試展開這個巨集。經過這個巨集的簡化,實際上必須有使用者自己完成的只有plugin_startup
這個函數了,這裡給使用者一個機會來完成外掛自身在啟動前要完成的工作。
需要注意的是,外掛的呼叫順序是與註冊的順序相同的。
4. 進入事件等待
application::exec
函式啟動一個boost::asio::io_service
並監聽了幾個訊號:SIGINT / SIGTERM / SIGPIPE
,並阻塞在
io_serv->run();
這行程式碼,當程序收到這幾個訊號中的一個的時候,阻塞函式返回,並進入
shutdown
函式。
5. 程式退出
觀察示例程式碼我們發現並沒有顯式呼叫
application::shutdown
函式,實際上這是由上一步驟中監聽的事件來觸發的,也就是類似CTRL+C
這樣的鍵盤時間或者kill
之類的命令觸發的。
在這個函式中,會逐一的呼叫外掛的shutdown
函式,時間上就是使用者自己編寫的
plugin_shutdown
函式。
需要注意的是,shutdown
中呼叫外掛的順序是與startup
的時候的順序相反的,也就是註冊的相反的順序。
總結
綜合上述的流程,我們發現基於AppBase
編寫一個程式主要的工作就是編寫外掛,而完成一個外掛的流程就是如下簡單幾個步驟:
appbase::plugin APPBASE_PLUGIN_REQUIRES plugin_initialize plugin_startup plugin_shutdown
對於AppBase的實現細節我的fork專案andyzhshg/appbase
裡的註釋解釋的比較詳細了。其中有一部分是關於method
和channel
的,AppBase
本身的示例並沒有演示用法,這篇文章沒有解釋,也許後續研究EOS的過程中我會回頭解釋這個設計。