我们使用Apache服务器时大多会自己开发新的模块用来进行数据传输,还会将自己定义的文件加入到服务中,这个过程相当于对Apache进行二次开发。
Apache的模块应该包括一个module对象,这里称呼对象不合适,因为C里面没有对象的概念,如下面这个,
module AP_MODULE_DECLARE_DATA epgs_db_module =
{
STANDARD20_MODULE_STUFF,
NULL,
NULL,
create_db_config,
NULL,
db_cmds,
register_hooks
};
Module是Apache定义的模块结构体,定义如下,
typedef struct module_struct module;
struct module_struct {
/** API version, *not* module version; check that module is
* compatible with this version of the server.
*/
int version;
/** API minor version. Provides API feature milestones. Not checked
* during module init */
int minor_version;
/** Index to this modules structures in config vectors. */
int module_index;
/** The name of the module's C file */
const char *name;
/** The handle for the DSO. Internal use only */
void *dynamic_load_handle;
/** A pointer to the next module in the list
* @defvar module_struct *next */
struct module_struct *next;
/** Magic Cookie to identify a module structure; It's mainly
* important for the DSO facility (see also mod_so). */
unsigned long magic;
/** Function to allow MPMs to re-write command line arguments. This
* hook is only available to MPMs.
* @param The process that the server is running in.
*/
void (*rewrite_args) (process_rec *process);
/** Function to allow all modules to create per directory configuration
* structures.
* @param p The pool to use for all allocations.
* @param dir The directory currently being processed.
* @return The per-directory structure created
*/
void *(*create_dir_config) (apr_pool_t *p, char *dir);
/** Function to allow all modules to merge the per directory configuration
* structures for two directories.
* @param p The pool to use for all allocations.
* @param base_conf The directory structure created for the parent directory.
* @param new_conf The directory structure currently being processed.
* @return The new per-directory structure created
*/
void *(*merge_dir_config) (apr_pool_t *p, void *base_conf, void *new_conf);
/** Function to allow all modules to create per server configuration
* structures.
* @param p The pool to use for all allocations.
* @param s The server currently being processed.
* @return The per-server structure created
*/
void *(*create_server_config) (apr_pool_t *p, server_rec *s);
/** Function to allow all modules to merge the per server configuration
* structures for two servers.
* @param p The pool to use for all allocations.
* @param base_conf The directory structure created for the parent directory.
* @param new_conf The directory structure currently being processed.
* @return The new per-directory structure created
*/
void *(*merge_server_config) (apr_pool_t *p, void *base_conf,
void *new_conf);
/** A command_rec table that describes all of the directives this module
* defines. */
const command_rec *cmds;
/** A hook to allow modules to hook other points in the request processing.
* In this function, modules should call the ap_hook_*() functions to
* register an interest in a specific step in processing the current
* request.
* @param p the pool to use for all allocations
*/
void (*register_hooks) (apr_pool_t *p);
};
这里补充一下:epgs_db_module里面STANDARD20_MODULE_STUFF是一个宏,它包含了一系列的参数,所以epgs_db_module看起来跟module定义不对齐,其实是对齐的。
这个数据结构很长 但是我们这里不需要全都看,跟文件加载相关的有两个,一个是函数,我们epgs_db_module里面是create_db_config,这个其实跟模块加载有关系,用来在模块加载时调用,另一个是command_rec,在加载文件时调用,这里我们epgs_db_module里面是db_cmds,我们在程序里定义了他
static const command_rec db_cmds[] =
{
AP_INIT_RAW_ARGS("DBPath", set_db_path, NULL, OR_FILEINFO,
"配置DB数据集文件路径"),
{NULL}
};
这里的参数DBPath就是用来标志哪个模块可以处理这个文件的,当我们读配置文件时,我们先把文件到一个链表中,当然这个链表中不只有文件数据也有其他的一些配置信息,这些信息都是与服务有关的,Apache会调用相关的模块进行处理,流程跟处理文件类似,读到链表中之后首先遍历这个链表,然后通过查找模块链表将对应的处理模块找出来,具体如下,
ap_str_tolower(dir);
ml = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING);
APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht,
const void *key,
apr_ssize_t klen)
{
apr_hash_entry_t *he;
he = *find_entry(ht, key, klen, NULL);
if (he)
return (void *)he->val;
else
return NULL;
}
找到模块之后就可以直接调用第二个参数,一个函数,就可以进行加载了。