apache 2的一个好处,就是可以方便的添加余户自定义的hook,而不需要全局统一。
我们通过编写一个简单的挂钩同时在模块中使用该挂钩从而来加深理解上面所分析的内容。比如现在我们定义在了一个能够在Apache处理请求时调用的函数some_hook,其函数原型为:
int some_hook(request_rec* r,int n);
那么我们分为四个步骤来声明我们的挂钩。
(1)、挂钩声明
我们使用AP_DECLARE_HOOK宏声明一个名称为some_hook的挂钩,声明如下:
AP_DECLARE_HOOK(int,some_hook,(request_rec* r,int n))
(2)、挂钩数组声明
由于some_hook是新声明的挂钩,为此,我们必须同时声明新的挂钩数组来保存各个模块对挂钩的注册使用。声明的语句如下:
APR_HOOK_STRUCT(
APR_HOOK_LINK(some_hook)
……
)
(3)、声明函数调用类型
挂钩声明完毕之后,真正被ap_run_name调用之前,我们还必须声明挂钩的调用类型,或者是VOID类型,或者是FIRST类型,或者是ALL类型。此处我们声明some_hook挂钩为VOID类型,声明语句如下:
AP_IMPLEMENT_HOOK_RUN_VOID(some_hook,(request_rec* r,int n),(r,n))
定义完该宏,实际上也对外声明了该挂钩的执行函数ap_run_some_hook。
(4)、注册挂钩函数
至第三步为止,对挂钩的声明已经基本结束,也意味着下一步的工作实际上应该落实到挂钩使用者身上了。比如如果模块som_module中想使用挂钩some_hook,则其必须在挂钩注册函数中注册该挂钩,挂钩注册函数为ap_hook_some_hook,代码示例如下:
static void register_hooks()
{
……
ap_hook_some_hook(some_hook_function,NULL,NULL,HOOK_MIDDLE);
}
AP_DECLARE_DATA module core_module = {
……
register_hooks /* register hooks */
};
(5)、编写挂钩函数
最后剩下的内容就是编写具体的挂钩调用函数。比如在some_module模块中,我们希望挂钩函数只是打印出“Hello World”语句,而且从(4)中看出挂钩函数名称为some_hook_function,因此挂钩函数声明为如下:
static void some_hook_function(request_rec* r,int n)
{
ap_rputs(“Hello World\n”);
return;
}
需要注意的是,这边的挂钩函数必须符合AP_IMPLEMENT_HOOK_RUN_XXX中声明的格式。