plugin.h 代码阅读笔记

发布: 2008-05-29 23:02

该文件中定义了lighttpd的模块插件结构体。此结构体大量使用了函数指针,对进一步深入了解函数指针很有现在。现在的工作是,解释结构体中每个字段的含义,用处,使用方法。搞清楚插件中几个函数的调用序列,插件中几个函数的返回值对lighttpd有什么影响。

[code type="c"]
#ifndef _PLUGIN_H_

#define _PLUGIN_H_

#include “base.h”

#include “buffer.h”

//此宏定义服务器函数的通用格式,参数为 server 类型指针,一个 指向模块定义的数据结构的void 类型指针

#define SERVER_FUNC(x) \

static handler_t x(server *srv, void *p_d)

#define CONNECTION_FUNC(x) \

static handler_t x(server *srv, connection *con, void *p_d)

#define INIT_FUNC(x) \

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]


原文: http://qtchina.tk/?q=node/144

Powered by zexport