apache中钩子的整体结构:
1 上面的 s_aHooksToSort 是为了对钩子函数进行排序使用而引入的 , 和它相关的操作都是在 apr_hooks.c 文件中
2 _hook 就是钩子数组,这里面的每个元素都是一个钩子,每个钩子对应着一系列的钩子函数 ( 最右边框中 ) ,实际程序中,同一个钩子对应的钩子函数形成一个数组,而不是这里画的链表
3 钩子的注册过程
A 每个模块都会调用 register_hooks 这个函数,在这个函数中,对本身模块的所有钩子一一进行注册( ap_hook_xxx )
B 这个函数实际会调用 APR_IMPLEMENT_EXTERNAL_HOOK_BASE
#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; /
}
① 如果挂钩还是空的,那么 在⑵ 这里为该挂钩分配一个数组来存放对应的挂钩函数,同时我们需要把这里新建的挂钩函数数组地址告诉s_aHooksToSort, 具体是在 ③ 调用apr_hook_sort_register 中完成的
最后,注册完毕就可以进行排序,这里就不介绍了。
4 挂钩调用
调用有三种方式( apr_hooks.h ):
1 AP_IMPLEMENT_HOOK_VOID 调用挂钩对应的所有挂钩函数,直到结束,返回值都是 void
2 AP_IMPLEMENT_HOOK_ALL 和上面一样,不同的是当摸个钩子函数调用发生错误的时候,就会终止调用
2 AP_IMPLEMENT_HOOK_FIRST 一旦找到合适的函数(返回值不等于 decline ) , 就结束
实际程序中,会通过 ap_run_xxx 来出发相应的调用,比如前面介绍的 helloWorld 程序就是 result = ap_run_handler(r); ( config.c:372 )来触发 AP_IMPLEMENT_HOOK_FIRST 这个宏的