5.5.3 挂钩链声明(APR_HOOK_LINK)
在Apache中,系统定义了一定数量的挂钩,这些挂钩总的来说可以分为两大类:启动挂钩和请求挂钩。启动挂钩是随着服务器启动进行调用的挂钩;而请求挂钩则是服务器处理请求时候进行调用的挂钩。这两种挂钩的实质唯一区别就是它们在服务器中的平均调用频率以及它们在被调用时候服务器充当的角色。所有启动挂钩作为启动服务器的用户进行调用,通常是指UNIX超级用户,而所有请求挂钩都是作为配置文件中指定的用户进行调用。
Apache中预定义了大量的挂钩,启动挂钩有pre_config、post_config、open_logs以及child_init;请求挂钩包括pre_connection、process_connection、create_request等等。Apache中声明的挂钩通常都是全局的,存在且仅存在一个。不过对应于挂钩的调用函数则通常不止一个。比如对于挂钩post_config,在核心模块core.c中调用的挂钩函数是core_post_config,在status模块mod_status.c中调用的挂钩函数是status_init,而在include模块mod_include.c中对应的挂钩函数则是include_post_config。对于同一个挂钩,不同模块对应于其的处理函数各不相同,为了能够保存各个模块中对同一挂钩的使用信息,Apache使用apr_array_header_t数组进行保存。
为此该宏的定义很简单,实际上无非就是声明了一个apr_array_header_t类型的数组,用来保存对应于某个挂钩的所有挂钩函数。比如APR_HOOK_LINK(post_config)展开后定义如下:
apr_array_header_t *link_post_config;
各个模块中对挂钩post_config进行处理的信息都保存在数组link_post_config中,其中link_post_config数组中每个元素的类型都是ap_LINK_post_config_t结构;当然不同的数组,其类型也不相同,不过形式上都是ap_LINK_XXXX格式的。关于挂钩的大部分信息都由这个结构提供。
5.5.4 挂钩结构(APR_HOOK_STRUCT)
正如前面所说,对于每一个挂钩,Apache都会定义一个apr_array_header_t数组来保存它的相关信息。通常,该数组定义在实现挂钩的文件中,比如在config.c文件Apache实现了header_parser、pre_config、post_config、open_logs、child_init以及handler、quick_handler、optional_fn_retrieve八个挂钩,那么该文件中就应该定义八个数组来保存它们的信息。一旦定义挂钩数组,那么该数组将在整个Apache中保持唯一。当某个模块想要使用该挂钩的时候,其就向模块内对于该挂钩的处理结构压入数组。为了便于各模块对数组的访问,原则上必须将数组声明为全局变量,这是最简单的实现方式。
不过Apache2.0中并不支持直接访问挂钩数组,因此你想直接将数据压入处理结构那是“妄想”。为此Apache2.0中引入了APR_HOOK_STRUCT宏。该宏定义如下:
#define APR_HOOK_STRUCT(members) \
static struct { members } _hooks;
该宏展开后实际上定义了一个限于模块内使用的结构_hook,该模块内实现的所有挂钩的对应数组都保存为_hook的成员。比如config.c中的APR_HOOK_STRUCT定义如下:
APR_HOOK_STRUCT(
APR_HOOK_LINK(header_parser)
APR_HOOK_LINK(pre_config)
APR_HOOK_LINK(post_config)
APR_HOOK_LINK(open_logs)
APR_HOOK_LINK(child_init)
APR_HOOK_LINK(handler)
APR_HOOK_LINK(quick_handler)
APR_HOOK_LINK(optional_fn_retrieve)
)
其展开后变为如下:
static struct{
apr_array_header_t *link_header_parser;
apr_array_header_t *link_pre_config;