pfn=APR_RETRIEVE_OPTIONAL_FN(some_fn);
5.5.8.3.可选函数的使用
5.5.9智能挂钩
5.5.10挂钩工作机制
在前面的部分,我们对挂钩进行了详细的分析,但是还缺乏一个整体上的概念。从整体上来看挂钩的工作机制可以用下图来描述:

一个模块从挂钩的角度来看,其最重要的无非是两个方面:挂钩注册函数和挂钩处理函数。挂钩注册函数通常是模块结构中的register_hooks函数指针,该函数指针将调用实际的挂钩注册函数进行挂钩注册。挂钩注册的过程很简单,通过宏ap_hook_xxx实现。比如上图中声明了两个挂钩abc和xyz。
与此同时,模块中也将声明与挂钩对应的挂钩函数,该挂钩被触发的时候,该函数将被调用。正如前面描述,可以使用宏ap_run_xxx触发指定的挂钩。不过挂钩的触发通常是由核心模块在对客户端请求进行处理的过程中进行。
我们来看一个具体的例子,这是核心模块中关于挂钩的部分。
从模块的结构中可以看出,模块结构中包含一个指针register_hook,该指针通常指向模块中的实际的挂钩注册函数,比如,对于核心模块而言,其挂钩注册函数register_hooks,那么结构中的该指针也为register_hooks:
AP_DECLARE_DATA module core_module = {
STANDARD20_MODULE_STUFF,
create_core_dir_config, /* create per-directory config structure */
merge_core_dir_configs, /* merge per-directory config structures */
create_core_server_config, /* create per-server config structure */
merge_core_server_configs, /* merge per-server config structures */
core_cmds, /* command apr_table_t */
register_hooks /* register hooks */
};
而具体的register_hooks函数则如下:
static void register_hooks(apr_pool_t *p)
{
ap_hook_create_connection(core_create_conn, NULL, NULL,
APR_HOOK_REALLY_LAST);
ap_hook_pre_connection(core_pre_connection, NULL, NULL,
APR_HOOK_REALLY_LAST);
ap_hook_post_config(core_post_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
ap_hook_translate_name(ap_core_translate,NULL,NULL,APR_HOOK_REALLY_LAST);
ap_hook_map_to_storage(core_map_to_storage,NULL,NULL,APR_HOOK_REALLY_LAST);
ap_hook_open_logs(ap_open_logs,NULL,NULL,APR_HOOK_REALLY_FIRST);
ap_hook_handler(default_handler,NULL,NULL,APR_HOOK_REALLY_LAST);
ap_hook_type_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
ap_hook_fixups(core_override_type,NULL,NULL,APR_HOOK_REALLY_FIRST);
ap_hook_access_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
ap_hook_create_request(core_create_req, NULL, NULL, APR_HOOK_MIDDLE);
APR_OPTIONAL_HOOK(proxy, create_req, core_create_proxy_req, NULL, NULL,