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

2019-03-22 12:04

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

第4章 Apache模块化体系结构

Apache模块化体系结构是本书介绍的重点内容之一,通过模块化,Apache可以很方便地进行第三方扩展及裁剪。本章详细介绍了模块数据结构,并对模块结构中成员的上下文进行介绍,包括指令表、挂钩、配置结构操作指针,可让读者能够透彻理解与模块相关的方方面面,不仅知其然,而且知其所以然。除此之外,本章还介绍了核心模块如何加载的过程,以及Apache模块通信所采用的各种策略,包括简单通信方式、可选函数通信方式及提供者API方式。本章最后对Apache中的一些常用模块进行了简单介绍。

4.1 Apache模块概述

Apache设计的一个最重要的目标就是扩展性能,用户可以根据自己的需要对Apache进行功能扩展。为此引出了模块的概念。Apache模块通常是指一些具有一定相对独立功能函数。送模块的角度讲,Apache有两部分组成:Apache核心和Apache模块。如果要扩展Apache功能,那么你 自行编写Apache模块或使用现有的Apache模块。

Apache的核心对其余模块的管理包括下面几个部分。 (1)非核心模块的注册和卸载。

(2)核心模块负责接收客户端的请求,并与非核心模块进行交互。

(3)挂钩、过滤器及可选函数的注册。

4.2 模块的加载

4.2.1 静态模块加载

Apache中对模块的家在处理是从main.c中的ap_setup_prelink_modules开始的:

error = ap_setup_prelinked_modules(process); if (error) { ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_EMERG,

0, NULL, \

destroy_and_exit_process(process, 1);}

它用于将当前Apache中的所有modules.c中预链接模块加载并激活,函数实现如下:

AP_DECLARE(const char*)ap_setup_prelinked_modules(process_rec*process) {

module **m; module **m2;

- 20 -

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

const char *error;

apr_hook_global_pool=process->pconf;

rebuild_conf_hash(process->pconf, 0); total_modules = 0;

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

(*m)->module_index = total_modules++;

加载的前期阶段工作包括创建指令名称的哈希表和初始化各个模块的索引值。

初始化的另一个工作是对ap_preloaded_modules进行索引标记,当初始化时可以看到各个模块的索引都被设置为-1。

ap_loaded_modules = (module **)apr_palloc(process->pool,

sizeof(module *) * (total_modules + DYNAMIC_MODULE_LIMIT + 1)); if (ap_loaded_modules == NULL) {

return \ for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; ) *m2++ = *m++; *m2 = NULL;

for (m = ap_prelinked_modules; *m != NULL; m++) { error = ap_add_module(*m, process->pconf); if (error) { return error;}

} apr_hook_sort_all(); return NULL; }

ap_loaded_modules数组用来保存所有的加载模块,即时模块没有激活,对于ap_preloaded_modules也不例外,因此作为初始化工作,有必要的将ap_preloaded_modules中的数组先添加到ap_loaded_modules数组中。以后如果需要新增加第三方模块,同样也添加到ap_loaded_modules数组中。

对于Apache2.0而言,ap_preloaded_modules数组中的模块都要被激活,为此,Apache还必须调用ap_add_module将它们添加到激活链表中。一旦激活所有的模块,函数便调用apr_hook_sort_all对所有模块内的钩子进行排序,以便于处理。

现在我们来看ap_add_module函数,其定义如下:

AP_DECLARE(const char *) ap_add_module(module *m, apr_pool_t *p){ if (m->version != MODULE_MAGIC_NUMBER_MAJOR) {

return apr_psprintf(p, \ \ \

m->name, m->version, MODULE_MAGIC_NUMBER_MAJOR);} if (m->next == NULL) {

- 21 -

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

m->next = ap_top_module; ap_top_module = m;}

if (m->module_index == -1) {

m->module_index = total_modules++; dynamic_modules++;

if (dynamic_modules > DYNAMIC_MODULE_LIMIT) {

return apr_psprintf(p, \ \ \

\ }

if (ap_strrchr_c(m->name, '/'))

m->name = 1 + ap_strrchr_c(m->name, '/'); if (ap_strrchr_c(m->name, '\\\\'))

m->name = 1 + ap_strrchr_c(m->name, '\\\\'); ap_add_module_commands(m, p); ap_register_hooks(m, p); return NULL; }

ap_add_module用于在服务器中激活制定模块m,通常它用于应对http.conf文件中的AddModule指令。

再将模块加入服务器之前,Apache必须判断模块的版本是否与当前Apache服务器的版本相同。Apache2.0所有模块的版本好统一为MODULE_MAGI- C_NUMBER_MAJOR,min_version则为MODULE_MAGIC_NUMBER_MINOR。

所有的模块最终都被加入到全局模块列表ap_top_module中,所有新增加的模块都被插入到ap_top_module链表的起始位置。一旦插入完成,Apache将对插入的模块进行索引标记。有一点要注意,累积的总模块数不能超过动态载入模块的最大数DYNAMIC_MODULE_LIMIT。

模块还必须将他们所有的指令处理函数加入到指令哈希表中,该过程由函数ap_add_module_commands完成,代码如下:

static void ap_add_module_commands(module *m, apr_pool_t *p){

apr_pool_t *tpool; ap_mod_list *mln;

const command_rec *cmd; char *dir;

cmd = m->cmds;

if (ap_config_hash == NULL) { rebuild_conf_hash(p, 0);}

tpool = apr_hash_pool_get(ap_config_hash); while (cmd && cmd->name) {

- 22 -

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

mln = apr_palloc(tpool, sizeof(ap_mod_list)); mln->cmd = cmd;

mln->m = m;

dir = apr_pstrdup(tpool, cmd->name); ap_str_tolower(dir);

mln->next = apr_hash_get(ap_config_hash, dir,

APR_HASH_ KEY_STRING);

apr_hash_set(ap_config_hash, dir, APR_HASH_KEY_STRING, mln); ++cmd;} }

如果指令哈希表不存在,则首先必须构建生成该指令哈希表,然后逐一遍历模块m中的指令表,并将它们插入到指令哈希表中对应的位置。

4.2.2 动态模块加载

大部分Apache标准模块都可以通过静态编译链接加载执行,不过对很多的第三方Apache模块却很难实现,而这些模块可以通过Apache的动态加载机制实现模块加载。

在分析每个模块之前,首先要分析的是模块的数据结构及该模块能够处理的指令表。对于mod_so模块也不例外,mod_so模块的结构和其中的指令如下所示:

static const command_rec so_cmds[] = {

AP_INIT_TAKE2(\ RSRC_CONF | EXEC_ON_READ,

\ AP_INIT_ITERATE(\

RSRC_CONF | EXEC_ON_READ,

\ { NULL } };

module AP_MODULE_DECLARE_DATA so_module = { STANDARD20_MODULE_STUFF,

NULL, /* create per-dir config */ NULL, /* merge per-dir config */ so_sconf_create, /* server config */

NULL, /* merge server config */ so_cmds, /* command apr_table_t */ register_hooks /* register hooks */};.

模块中能够处理的所有指令都保存在指令表so_cmds中,从中可以看出来,mod_so模块可以处理的指令只有“LoadModule”和“LoadFile”,相应的处理函数分别为load_module 和load_file。下面我们首先来看load_module函数的实现,

- 23 -

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

该函数也是模块装载处理的入口。

static const char *load_module(cmd_parms *cmd, void *dummy,

const char *modname, const char *filename) 该函数用来将共享对象载入到服务器地址空间中。其中,cmd和dummy是所有的指令程序必须有的,由于Apache核心给模块传递相应信息。modname是加载模块的名称,而filename是对应的.so文件的绝对路径名称。

{

apr_dso_handle_t *modhandle; apr_dso_handle_sym_t modsym; module *modp;

const char *szModuleFile = ap_server_root_relative(cmd->pool, filename);

so_server_conf *sconf;

ap_module_symbol_t *modi; ap_module_symbol_t *modie; int i;

const char *error;

*(ap_directive_t **)dummy = NULL; if (!szModuleFile) {

return apr_pstrcat(cmd->pool, \ filename, NULL);} sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config,

&so_module); modie = (ap_module_symbol_t *)sconf->loaded_modules->elts; for (i = 0; i < sconf->loaded_modules->nelts; i++) { modi = &modie[i];

if (modi->name != NULL && strcmp(modi->name, modname) == 0) { ap_log_perror(APLOG_MARK, APLOG_WARNING, 0,

cmd->pool, \%s is already loaded, skipping\

modname); return NULL;} }

函数首先检查参数szModuleFile制定的so文件是否存在,如果存在,下一步必须在现有的所有模块中查找需要载入的模块是否存在,如果该模块已载入,则无需做任何处理,否则对其进行加载。

for (i = 0; ap_preloaded_modules[i]; i++) { const char *preload_name; apr_size_t preload_len; apr_size_t thismod_len;

- 24 -


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

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

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

马上注册会员

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