基于Apache源代码的Web应用服务器的体系结构分析 论文(7)

2019-03-22 12:04

沈阳工程学院毕业论文 第4章 Apache模块化体系结构

modp = ap_preloaded_modules[i];

if (memcmp(modp->name, \ continue;}

preload_name = modp->name + strlen(\ preload_len = strlen(preload_name) - 2;

if (strlen(modname) <= strlen(\ continue;}

thismod_len = strlen(modname) - strlen(\ if (strcmp(modname + thismod_len, \ continue;}

if (thismod_len != preload_len) {

continue;}

if (!memcmp(modname, preload_name, preload_len)) { return apr_pstrcat(cmd->pool, \ \ NULL);} }

如果制定的模块没有被加载,那么函数将执行加载。对动态加载模块检查完毕后,Apache将检查静态链接模块数组ap_preloaded_modules。在ap_preloaded_modules数组中查找指定的模块相对简单。对于每一个模块,要阿Apache认定他是一个合法的模块,就必须符合:

(1)Apache必须保证其文件名是以\开始的。 (2)Apache必须保证其文件名是以\结束的。 modi = apr_array_push(sconf->loaded_modules); modi->name = modname; if (apr_dso_load(&modhandle, szModuleFile, cmd->pool) != APR_SUCCESS) {

char my_error[256];

return apr_pstrcat(cmd->pool, \ \

apr_dso_error(modhandle, my_error, sizeof(my_error)),

NULL);}

ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, cmd->pool, \

if (apr_dso_sym(&modsym, modhandle, modname) != APR_SUCCESS) { char my_error[256];

return apr_pstrcat(cmd->pool, \ modname, \ apr_dso_error(modhandle, my_error,

- 25 -

沈阳工程学院毕业论文 第4章 Apache模块化体系结构

sizeof(my_error)),

NULL);}

modp = (module*) modsym;

modp->dynamic_load_handle = (apr_dso_handle_t *)modhandle; modi->modp = modp;

一切检查完毕后,函数将对模块进行加载。加载分为两步骤。 (1)在module_so模块中保存当前新载入的模块信息。

(2)调用apr_dso_load将文件载入到Apache的地址空间中,同时调用apr_dso_sym获取动态库中的module结构,返回的结构保存在modsym中。

if (modp->magic != MODULE_MAGIC_COOKIE) {

return apr_psprintf(cmd->pool, \ \garbled - expected signature lx but saw \

\- perhaps this is not an Apache module DSO, \

\was compiled for a different Apache version?\

modname, szModuleFile, MODULE_MAGIC_COOKIE, modp->magic);}

error = ap_add_loaded_module(modp, cmd->pool); if (error) {

return error;}

在真正使用即激活加载模块前,Apache必须确保加载的模块确实是Apache没快。为此Apache在模块结构中设定了magic字段,通过检查magic字段,Apache确定加载的模块是否是Apache模块。如果加载的是合法的Apache模块,函数将立即调用ap_add_loaded_module蒋模块激活,所谓的激活无非是将模块放入ap_top_mudoles链表中。

apr_pool_cleanup_register(cmd->pool, modi, unload_module, apr_pool_cleanup_null);

ap_single_module_configure(cmd->pool, cmd->server, modp); return NULL; }

此外,Apache还需要在配置内存池pconf中注册cleanup函数。这样当我们重新启动或关闭服务器时,cleanup函数将自动调用并共享模块卸载。

动态加载模块最后一步是调用模块内部的create_server_config和create_dir_config指针创建模块服务器的相关配置和目录相关配置。它们的创建封装在ap_single_module_configure中。

实际的核心加载由ap_add_loaded_module完成,该函数的实现相对简单,如下:

- 26 -

沈阳工程学院毕业论文 第4章 Apache模块化体系结构

AP_DECLARE(const char *) ap_add_loaded_module(module *mod, apr_pool_t *p)

{

module **m; const char *error;

error = ap_add_module(mod, p); if (error) {

return error;}

for (m = ap_loaded_modules; *m != NULL; m++) ;

*m++ = mod;

*m = NULL; return NULL; }

ap_add_loaded_module函数完成的事情很简单,一方面它调用ap_add_module将模块增加到ap_top_module模块链表中,另一方面还要将模块增加到ap_loaded_modules加载模块链表中。

4.2.3 模块卸载

当一个模块不要再使用时,该模块就可以被卸载。Apache中并没有提供显示式的卸载模块的指令和接口,也就是说,一个模块一旦被加载,就无法再运行过程中被卸载。卸载的唯一办法就是修改配置文件或重新编译。

由于模块数据结构中所占用的内存也是从内存池中分配出来的,因此它遵循内存池的清理原则。当内存被释放时,模块数据结构调用自身的清理数据结构执行模块清理。模块的清理通过函数unload_module完成:

static apr_status_t unload_module(void *data){

ap_module_symbol_t *modi = (ap_module_symbol_t*)data; if (modi->modp == NULL) return APR_SUCCESS;

ap_remove_loaded_module(modi->modp); modi->modp = NULL; modi->name = NULL; return APR_SUCCESS; }

实际的模块卸载由ap_remove_loaded_module函数完成,该函数需要一个参数,即模块的数据描述结构:

AP_DECLARE(void) ap_remove_loaded_module(module *mod){ module **m; module **m2;

- 27 -

沈阳工程学院毕业论文 第4章 Apache模块化体系结构

int done;

ap_remove_module(mod);

for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) { if (*m2 == mod && done == 0) done = 1;

else

*m++ = *m2;} *m = NULL; }

整个移除过程分两步,首先必须从模块链表ap_top_module中将模块结构移除,该移除由ap_remove_module完成。

当模块从ap_top_module链表中被移除时,ap_loaded_modules中指向该模块的指针也要被设置为NULL。

4.3 指令表

4.3.1 指令表概述

模块的另外一项功能就是指令表。所谓指令表就是保存各个指令名称及该指令处理函数的数组,图4-1展示的是一个完整的指令构成。

图4-1 指令表构成

指令名称(name)指令处理函数(func)指令参数(cmd_data)指令覆盖类型(cmd_override)指令处理方式(cmd_how)指令返回提示(errmsg)一个指令包含六部分内容,但与模块最紧密相连的是前两个成员,后面的四个成员都是指令本身的信息。

4.3.2 指令处理函数

关于指令处理函数,它与普通的函数没有太多区别,只有两个特殊的地方:一是参数,另一个是返回值。

- 28 -

沈阳工程学院毕业论文 第4章 Apache模块化体系结构

1.参数

所有的指令处理函数,它的前两个参数都是cmd_parms和void*类型,这可以从指令处理函数的类型看出:

typedef union {

const char *(*no_args) (cmd_parms *parms, void *mconfig);

const char *(*raw_args) (cmd_parms *parms, void *mconfig, const char *args);

const char *(*take_argv) (cmd_parms *parms, void *mconfig, int argc, char *const argv[]);

const char *(*take1) (cmd_parms *parms, void *mconfig, const char *w); const char *(*take2) (cmd_parms *parms, void *mconfig, const char *w, const char *w2);

const char *(*take3) (cmd_parms *parms, void *mconfig, const char *w, const char *w2, const char *w3);

const char *(*flag) (cmd_parms *parms, void *mconfig, int on); } cmd_func;

第一个参数是cmd_parms类型,定义在httpd_config.h中。cmd_parms结果会包含各种信息,所有信息至少会适用于一个指令,它是一个大杂烩,只要处理函数中可能需要的参数都会杯赛导致该结构体中。

除了cmd_parms参数外,指令处理函数的另外一个参数就是mconfig,它是void指针类型。各个指令处理函数所需要的参数不尽相同,可以通过mconfig传入。

2.返回值

指令处理函数的返回值只有三种:NULL、DECLINE_CMD及错误字符串。 如果指令处理函数能正常处理完某个指令,那么函数将返回NILL;如果在处理过程中发生了错误,那么函数将返回一个字符串用于描述发生的错误。

第三种情况比较难理解,就是返回DECLINE_CMD,它被定义为“\\a\\b\\”。该返回值在极少数场合下才会被使用。

4.4 挂钩(HOOK)

4.4.1 声明挂钩

Apache中关于挂钩的实现大部分是通过宏来完成的,而且这些宏大多数非常复杂。挂钩的实现主要定义在文件apr_hook.h和apr_hook.c中,另外在congfig.c中也有部分定义。

Apache中对挂钩的使用总是从定义一个挂钩开始的,在Apache中声明一个挂钩,总是通过如下的宏来实现的。

#define AP_DECLARE_HOOK(ret,name,args) \\

APR_DECLARE_EXTERNAL_HOOK(ap,AP,ret,name,args)

- 29 -


基于Apache源代码的Web应用服务器的体系结构分析 论文(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:苏教版语文五年级上册单元要点总结及练习

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: