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

2019-03-22 12:04

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

在该宏中,,ret是定义挂钩的返回类型,而name则是定义挂钩的名称;args则是挂钩函数需要的额外参数,通常以bracket形势出现。例如下面的语句就声明了一个返回类型为整数,函数名称为do_something,函数参数为(request_rec *r,int n)的挂钩;

AP_DECLARE_HOOK(int, do_something, (request_rec *r,int n)) 不过,AP_DECLARE_HOOK内部则是调用的APR_DECLARE_EXTERNAL _HOOK宏,该宏定义如下:

#define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \\ typedef ret ns##_HOOK_##name##_t args; \\

link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \\ const char * const *aszPre, \\

const char * const *aszSucc, int nOrder); \\ link##_DECLARE(ret) ns##_run_##name args; \\

APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \\ typedef struct ns##_LINK_##name##_t \\ { \\

ns##_HOOK_##name##_t *pFunc; \\ const char *szName; \\

const char * const *aszPredecessors; \\ const char * const *aszSuccessors; \\ int nOrder; \\

} ns##_LINK_##name##_t;

该宏进一步替换展开后为APR_DECLARE_EXTERNAL_HOOK(ap,AP,int, post_config,(apr_pool_t *pconf,apr_pool_t *plog,apr_pool_t *ptemp,server_rec *s) ),声明一个挂钩宏需要五部分内容。

(1)定义挂钩的执行函数原型:typedef ret ns##_HOOK_##name##_t args; (2)定义挂钩注册函数的原型:

link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \\ const char * const *aszPre, \\

const char * const *aszSucc, int nOrder); \\ (3)声明挂钩的调用函数:ink##_DECLARE(ret) ns##_run_##name args; (4)APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); 该宏展开如下所示:

#define APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \\ link##_DECLARE(apr_array_header_t *) ns##_hook_get_##name(void) 该宏用于返回挂钩访问函数原型,在模块外部可以调用该函数获得注册为该挂钩的所有函数。

(5)typedef struct ns##_LINK_##name##_t \\ { \\

ns##_HOOK_##name##_t *pFunc; \\

- 30 -

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

const char *szName; \\

const char * const *aszPredecessors; \\ const char * const *aszSuccessors; \\ int nOrder; \\

} ns##_LINK_##name##_t;

该宏定义了一个结构类型,用来保存挂钩的相关信息,这些信息与在挂钩定义宏中的信息完全相同。

至此,与挂钩关联的五个方面都已经声明完毕了。

4.4.2 挂钩数组声明

在Apache中,系统定义了一定数量的挂钩,这些挂钩总的来说可以分为两大类:启动挂钩和请求挂钩。启动挂钩是随着服务器启动进行调用的挂钩。而请求挂钩则是服务器处理请求时进行调用的挂钩。对于同一个挂钩,不同模块对应的处理函数各不相同,为了能够保存各个模块中对同一挂钩的实用信息,Apache核心使用apr_array_header_t数组进行保存,该书组通过宏APR_HOOK_LINK声明:

#define APR_HOOK_LINK(name) \\ apr_array_header_t *link_##name;

该宏定义很简单,实际上就是声明了一个apr_array_header_t类型数组,用来保存对应某个挂钩的所有挂钩函数。

4.4.3 挂钩结构

对于每一个挂钩,Apache都会顶一个apr_array_header_t数组来保存它的相关信息。一旦定义了挂钩数组,该数组将在整个Apache中保持唯一。当某个模块想要使用该挂钩的时候,只要访问模块内对应的挂钩数组即可。

不过,Apache2.0中并不支持直接访问挂钩数组,因此,你想直接将数据压入数组是不可能的。Apache2.0中引入了APR_HOOK_STRUCT宏,所有对数组的操作都只能通过该红来实现。该宏定义如下:

#define APR_HOOK_STRUCT(members) \\ static struct { members } _hooks;

该宏展开后实际上定义了一个限于模块内使用的结构_hooks,该模块内部实现的所有挂钩的对应数组都保存为_hook的成员。

Apache中对挂钩数组的访问都必须通过_hook来实现。 不过有几点必须注意的是:

(1)_hook在某个文件中只能定义一次。

(2)_hook的定义为static,这意味着该结构实际上是模块内部的私有结构,外部模块无法直接访问_hook结构。

- 31 -

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

4.4.4 挂钩函数注册

从宏的名字我们就可以大体看出,该宏实际上是实现了具体的挂钩注册函数。该宏定义如下所示:

#define APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \\

link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf,

const char * const *aszPre, \\

const char * const *aszSucc,int nOrder) \\ { \\

ns##_LINK_##name##_t *pHook; \\ if(!_hooks.link_##name) \\

{ \\

_hooks.link_##name=apr_array_make(apr_hook_global_pool,1,sizeof(ns##_LINK_##name##_t)); \\

apr_hook_sort_register(#name,&_hooks.link_##name); \\ } \\

pHook=apr_array_push(_hooks.link_##name); \\ pHook->pFunc=pf; \\

pHook->aszPredecessors=aszPre; \\ pHook->aszSuccessors=aszSucc; \\ pHook->nOrder=nOrder; \\ pHook->szName=apr_hook_debug_current; \\ if(apr_hook_debug_enabled) \\

apr_hook_debug_show(#name,aszPre,aszSucc); \\ } \\

APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \\ { \\

return _hooks.link_##name; \\ }

挂钩注册函数首先检查挂钩数组是否为空,如果为空,则说明是第一次注册该挂钩,然后创建新数组并注册该挂钩类型以供以后排序用;否则,直接加入一条新纪录。

4.4.5 使用挂钩

Apache中挂钩调用函数形式通常如ap_run_HOOKNAME所示,比如ap_run_post_config就是调用post_config挂钩。尽管所有的挂钩对外提供的形式都是一样的,但是内部实现却不相同,差别分别体现于三个宏:AP_IMPLE- MENT_HOOK_VOID、AP_IMPLEMENT_HOOK_RUN_FIRST及AP_IMPLEM- ENT_HOOK_RUN_ALL。

- 32 -

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

1.对于AP_IMPLEMENT_HOOK_VOID,调用函数将遍历挂钩数组,逐个执行针对该挂钩的所有注册过的挂钩函数,直到遍历调用结束。这种类型通常称为VOID,由于它没有任何返回值,其声明如下:

#define

APR_IMPLEMENT_EXTERNAL_HOOK_VOID(ns,link,name,args_decl,args_use) \\

APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \\ link##_DECLARE(void) ns##_run_##name args_decl \\ { \\

ns##_LINK_##name##_t *pHook; \\ int n; \\ \\

if(!_hooks.link_##name) \\ return; \\ \\

pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \\ for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \\ pHook[n].pFunc args_use; \\ } 2.AP_IMPLEMENT_HOOK_RUN_ALL简称ALL类型,它与AP_IMPLEME- NT _ HOOK_VOID几乎相同,唯一不同的是ALL类型具有返回值。宏声明如下:

#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ns,link,ret,name,args_decl,

args_use,ok,decline) \\

APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \\ link##_DECLARE(ret) ns##_run_##name args_decl \\ { \\

ns##_LINK_##name##_t *pHook; \\ int n; \\ ret rv; \\ \\

if(!_hooks.link_##name) \\

return ok; \\ \\

pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \\ for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \\ { \\

rv=pHook[n].pFunc args_use; \\ \\

if(rv != ok && rv != decline) \\ return rv; \\

- 33 -

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

} \\

return ok; \\

}

3.AP_IMPLEMENT_HOOK_RUN_FIRST简称FIRST类型,对于该类型,Apache核心从头逐一遍历挂钩数组中所注册的挂钩函数,直到遇到一个能够完

成所提交任务的函数或发生错误为止。该宏定义如下:

#define

APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ns,link,ret,name,args_decl,

args_use,decline) \\

APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \\ link##_DECLARE(ret) ns##_run_##name args_decl \\

{ \\

ns##_LINK_##name##_t *pHook; \\ int n; \\ ret rv; \\ \\

if(!_hooks.link_##name) \\ return decline; \\ \\

pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \\ for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \\

{ \\

rv=pHook[n].pFunc args_use; \\ \\

if(rv != decline) \\ return rv; \\ } \\

return decline; \\ }

任何挂钩都必须且只能是三类型中的一种,任何挂钩在被执行之前都必须调用这三个宏中的一个进行声明。

- 34 -


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

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

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

马上注册会员

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