plugin.h 代碼閱讀筆記
該檔案中定義了lighttpd的子產品插件結構體。此結構體大量使用了函數指針,對進一步深入了解函數指針很有現在。現在的工作是,解釋結構體中每個字段的含義,用處,使用方法。搞清楚插件中幾個函數的調用序列,插件中幾個函數的傳回值對lighttpd有什麼影響。
[code type="c"]
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
#include “base.h”
#include “buffer.h”
//此宏定義伺服器函數的通用格式,參數為 server 類型指針,一個 指向子產品定義的資料結構的void 類型指針
#define SERVER_FUNC(x) \r
static handler_t x(server *srv, void *p_d)
#define CONNECTION_FUNC(x) \r
static handler_t x(server *srv, connection *con, void *p_d)
#define INIT_FUNC(x) \r
static void *x()
//下面四個是伺服器級别的函數
#define FREE_FUNC SERVER_FUNC
#define TRIGGER_FUNC SERVER_FUNC
#define SETDEFAULTS_FUNC SERVER_FUNC
#define SIGHUP_FUNC SERVER_FUNC
//下面五個是連接配接級别的函數
#define SUBREQUEST_FUNC CONNECTION_FUNC
#define JOBLIST_FUNC CONNECTION_FUNC
#define PHYSICALPATH_FUNC CONNECTION_FUNC
#define REQUESTDONE_FUNC CONNECTION_FUNC
#define URIHANDLER_FUNC CONNECTION_FUNC
#define PLUGIN_DATA size_t id //這個定義的是所有子產品插件的内部資料都必須有一個公共字段,這個字段的值由lighttpd統一管理,類似于一個序列值,給每個子產品都定義一個ID号。
//子產品插件結構體,包含的資訊相當的豐富。
typedef struct {
size_t version; //一般寫為 : LIGHTTPD_VERSION_ID 什麼時候不一樣呢。
buffer *name; /* name of the plugin */ //一般寫為子產品的名字 , 如 mod_skeleton
//下面這些函數指針指向的函數是要編寫子產品的開發人員實作的,當然,有些是可選的,有些是必須實作的。
void *(* init) (); //在加載目前子產品的時候調用,但不是第一個要調用的函數。在此之前會調用 *_plugin_init 函數初始化目前子產品。它是第一個實際調用的插件函數。此函數用于初始化子產品内部資料結構,此内部資料結構被賦給*plugin_init中設定的data字段了。
handler_t (* set_defaults) (server *srv, void *p_d); //實際調用的第二個插件函數。此函數是配置檔案解析入口。它應該傳遞一個選項參數清單給config_insert_values函數,并且還要檢查參數是否有效,如果是無效參數,則需要給該選項參數設定預設值,或者傳回錯誤。
handler_t (* cleanup) (server *srv, void *p_d); //最後一個調用的子產品插件函數。用于清理目前子產品使用的記憶體。它在目前子產品被解除安裝的前一該被lighttpd調用。
/* is called … */
handler_t (* handle_trigger) (server *srv, void *p_d); /* once a second */ //每一秒都會調用的插件函數,子產品如果不需要此定時器,可以忽略它。
handler_t (* handle_sighup) (server *srv, void *p_d); /* at a signup */ //如果lighttpd收到SIGHUP信号,則它會調用插件中的這個函數,通知插件做相應處理。lighttpd收到這個信号時并不會退出,因而對子產品來說可以忽略這個信号。這個函數的調用順序不定,在子產品被加載之後,被解除安裝之前的任何時刻都可能調用此函數,這依賴于使用者行為,使用者可能手工向lighttpd發送SIGHUP信号。
handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d); /* after uri_raw is set */ //在lighttpd 設定了 uri_raw之後被調用。uri_raw是在什麼時候設定的呢?
handler_t (* handle_uri_clean) (server *srv, connection *con, void *p_d); /* after uri is set */ //在lighttpd設定了uri.path 之後被調用。uri.path是在什麼時候設定的呢?
handler_t (* handle_docroot) (server *srv, connection *con, void *p_d); /* getting the document-root */ //當 lighttpd 需要docroot的時候此函數被調用。 不太明白這個docroot的意思,lighttpd為什麼會不定時的需要 docroot 呢?
handler_t (* handle_physical) (server *srv, connection *con, void *p_d); /* mapping url to physical path */ // 在lighttpd設定了physical.path之後被調用。
handler_t (* handle_request_done) (server *srv, connection *con, void *p_d); /* at the end of a request */ //在請求結束的時候被調用,這個時候是否已經處理了請求并将資料發送到了用戶端了呢?
handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d); /* at the end of a connection */ //在連接配接終止的時候被調用。這時候請求的響應資料肯定已經發送到了客戶。
handler_t (* handle_joblist) (server *srv, connection *con, void *p_d); /* after all events are handled */ // 當此次請求的連接配接狀态發生變化時此函數被調用。連接配接狀态類型定義: connection_state_t
handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d); //在設定了physical.path之後被調用。這和 handle_physical函數有什麼差別呢。
/* when a handler for the request
* has to be found
*/
handler_t (* handle_subrequest) (server *srv, connection *con, void *p_d); /* */ //?????
handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* */ //在每次請求的最後調用。這和 handle_request_close ,handle_request_done 有什麼關系,好象是在這兩 個調用中間某個時刻調用的???
void *data; //這個是指向子產品内部資料結構的指針。
/* dlopen handle */
void *lib; //dlopen 目前子產品時傳回的指向此子產品動态庫的指針變量。用于 dlclose, dlsym , dlerror 函數調用。
} plugin;
int plugins_load(server *srv);
void plugins_free(server *srv);
//與結構體中的函數指針對應的函數調用,一一對應。其實子產品插件中的函數指針是在下面這些函數中被調用的。
handler_t plugins_call_handle_uri_raw(server *srv, connection *con);
handler_t plugins_call_handle_uri_clean(server *srv, connection *con);
handler_t plugins_call_handle_subrequest_start(server *srv, connection *con);
handler_t plugins_call_handle_subrequest(server *srv, connection *con);
handler_t plugins_call_handle_request_done(server *srv, connection *con);
handler_t plugins_call_handle_docroot(server *srv, connection *con);
handler_t plugins_call_handle_physical(server *srv, connection *con);
handler_t plugins_call_handle_connection_close(server *srv, connection *con);
handler_t plugins_call_handle_joblist(server *srv, connection *con);
handler_t plugins_call_connection_reset(server *srv, connection *con);
handler_t plugins_call_handle_trigger(server *srv);
handler_t plugins_call_handle_sighup(server *srv);
handler_t plugins_call_init(server *srv);
handler_t plugins_call_set_defaults(server *srv);
handler_t plugins_call_cleanup(server *srv);
int config_insert_values_global(server *srv, array *ca, const config_values_t *cv);
int config_insert_values_internal(server *srv, array *ca, const config_values_t *cv);
int config_setup_connection(server *srv, connection *con);
int config_patch_connection(server *srv, connection *con, comp_key_t comp);
int config_check_cond(server *srv, connection *con, data_config *dc);
int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
#endif
[/code]