上面一篇文章大致描述了一下外掛程式開發架構整體結構。這篇描述一下核心層的設計和實現。
至於核心層的設計,我想借鑒 一下微核心的思想。核心層只負責實現下面幾個功能:
1、 外掛程式的載入,檢測,初始化。
2、 服務的註冊。
3、 服務的調用。
4、 服務的管理。
外掛程式的載入,檢測,初始化
外掛程式的載入利用linux共用庫的動態載入技術。具體的方法可以看一下IBM網站的一篇資料《Linux 動態庫剖析》 。
服務的註冊
服務的註冊與調用採用表驅動的方法。核心層中維護一個服務註冊表。
//外掛程式間互動訊息類型
typedef enum __Service_Type
{
Service_Max,
}Service_Type;
//外掛程式用於和其他外掛程式通訊介面函數,由外掛程式提供。
typedef PRsp_Ele_Stream (*PF_Invoke_Service_Func)(PReq_Ele_Stream pele_str);
//驅動表
typedef PF_Invoke_Service_Func Service_Drive_Table[Service_Max];
驅動表是一個數組,下標為外掛程式間互動訊息類型,成員為外掛程式提供的接收的訊息處理函數,由外掛程式初始化的時候,調用外掛程式架構的的註冊函數註冊到驅動表。
外掛程式的初始化實現為:
//外掛程式用於註冊處理的訊息類型的函數,由外掛程式架構提供。
typedef RET_RESULT (*PF_Service_Register_Func)(Service_Type service_type);
//外掛程式用於和其他外掛程式通訊介面函數,由外掛程式架構提供。
typedef PRsp_Ele_Stream (*PF_Invoke_Service_Func)(PReq_Ele_Stream pele_str);
//外掛程式回複響應函數。外掛程式收到非同步請求後,處理完成後,發送響應訊息給請求的外掛程式。由外掛程式架構提供
typedef void (*PF_Send_Response_Func)(PRsp_Ele_Stream pele_str);
//初始化外掛程式資訊
typedef struct Plugin_Init_St
{
PF_Service_Register_Func register_func;//服務註冊函數,要註冊一系列的枚舉值。外掛程式可以處理的服務枚舉值
PF_Invoke_Service_Func invoke_serv_func;//和其他組件互動時,調用的用於和其他組件互動的函數。發送請求訊息。
PF_Send_Response_Func send_rsp_func;//再設計一個回複響應訊息的介面。收到非同步請求後,處理完畢後通知請求模組處理結果。
} Plugin_Init_St, *PPlugin_Init_St;
//初始化外掛程式函數,類似於建構函式。由外掛程式提供,供外掛程式架構載入外掛程式時初始化外掛程式使用。
void PF_Init_Plugin(PPlugin_Init_St pinit_info);
外掛程式在函數PF_Init_Plugin中調用函數register_func來註冊外掛程式要處理的訊息類型。
服務的調用
//信元結構體
typedef struct Ele_St
{
Ele_Tag tag;
Ele_Length len;
Ele_Value value;
PEle_St next;
}Ele_St, *PEle_St;
//請求訊息,信元流格式。
typedef struct Req_Ele_Stream
{
Plugin_ID src_id;//源外掛程式id
Service_Type req_type;//請求類型
PEle_St ele;
} Req_Ele_Stream, *PReq_Ele_Stream;
//響應訊息,信元流格式。
typedef struct Rsp_Ele_Stream
{
Plugin_ID dest_id;//目的外掛程式id
Service_Type req_type;//響應對應的請求的類型。
Execute_Result result;//記錄執行結果
Execute_Reason reason;//記錄執行結果的原因
PEle_St ele;
} Rsp_Ele_Stream, *PRsp_Ele_Stream;
//接收外掛程式調用服務要求函數,由外掛程式提供,入參為請求信元流。傳回值為響應信元流,用於同步請求處理。
PRsp_Ele_Stream PF_Receive_Invoke_Proc(PReq_Ele_Stream pele_str);
//外掛程式收到響應訊息的處理入口函數,由外掛程式提供。如此為響應信元流。
void PF_Receive_Rsponse_Porc(PRsp_Ele_Stream pele_str);
外掛程式間的依賴關係是通過信元流來實現的。至於信元流的使用在我的另一篇部落格《使用信元流(TLVStream)規範、簡化模組(C/C++)間互動 》 中有描述。外掛程式對外的介面都是統一的。
如果外掛程式要和其他的外掛程式通訊,則調用PF_Init_Plugin函數的傳遞的服務調用介面: invoke_serv_func。外掛程式架構根據信元流的類型,尋找驅動表,找到對應的服務接收函數。外掛程式用函數 PF_Receive_Invoke_Proc接受其他外掛程式的請求,此函數是外掛程式想外掛程式架構主動註冊到驅動表的。
如果服務時同步的,這直接通過此函數返回,返回的資訊在響應信元流中。如果是非同步請求,這外掛程式在處理完成後,通過 send_rsp_func函數來發送響應。
外掛程式的卸載
//卸載外掛程式時調用的函數,類似於解構函式。由外掛程式提供,供外掛程式架構卸載外掛程式時調用。
void PF_Destroy_Func();