这是我的页面头部

apache2 流程控制

_hook 数据结构
 1 
 2 // 从 ap_hook 到 ap_run
 3 // 宏 AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),OK,DECLINED ); 的具体实现
 4 // connection.c
 5     AP_DECLARE(void) ap_hook_pre_connection(ap_HOOK_pre_connection_t *pf, const char * const *aszPre, const char * const *aszSucc,int nOrder)
 6     { 
 7         ap_LINK_pre_connection_t *pHook; 
 8         if(!_hooks.link_pre_connection)
 9         {
10             _hooks.link_pre_connection=apr_array_make(apr_hook_global_pool,1,sizeof(ap_LINK_pre_connection_t)); 
11             apr_hook_sort_register("pre_connection",&_hooks.link_pre_connection); 
12         } 
13         pHook=apr_array_push(_hooks.link_pre_connection); 
14         pHook->pFunc=pf; 
15         pHook->aszPredecessors=aszPre; 
16         pHook->aszSuccessors=aszSucc; 
17         pHook->nOrder=nOrder; 
18         pHook->szName=apr_hook_debug_current; 
19         if(apr_hook_debug_enabled) 
20             apr_hook_debug_show("pre_connection",aszPre,aszSucc); 
21     } 
22     AP_DECLARE(apr_array_header_t *) ap_hook_get_pre_connection(void
23     { 
24         return _hooks.link_pre_connection; 
25     }
26     AP_DECLARE(int) ap_run_pre_connection (conn_rec *c, void *csd)
27     { 
28         ap_LINK_pre_connection_t *pHook; int n; int rv; 
29         if(!_hooks.link_pre_connection) 
30             return OK; 
31         pHook=(ap_LINK_pre_connection_t *)_hooks.link_pre_connection->elts; 
32         for(n=0 ; n < _hooks.link_pre_connection->nelts ; ++n)
33         { 
34             rv=pHook[n].pFunc (c, csd); 
35             if(rv != OK && rv != DECLINED) return rv;
36         } 
37         return OK; 
38     };

 

解码解释:

第5行 ap_hook_pre_connection 的第一个参数 pf 数据类型为 ap_HOOK_pre_connection_t ,实际是一个函数指针。也是用宏定义的:

// 宏 AP_DECLARE_HOOK(int,pre_connection,(conn_rec *c, void *csd))展开
// http_connection.h
typedef int ap_HOOK_pre_connection_t (conn_rec *c, void *csd);

AP_DECLARE(
void) ap_hook_pre_connection(ap_HOOK_pre_connection_t *pf, const char * const *aszPre, const char * const *aszSucc, int nOrder); 
AP_DECLARE(
int) ap_run_pre_connection (conn_rec *c, void *csd); 
AP_DECLARE(apr_array_header_t 
*) ap_hook_get_pre_connection(void); 
typedef 
struct ap_LINK_pre_connection_t 
{    
    ap_HOOK_pre_connection_t 
*pFunc; 
    
const char *szName; 
    
const char * const *aszPredecessors; 
    
const char * const *aszSuccessors; 
    
int nOrder;
} ap_LINK_pre_connection_t;

 

第7 行的 _hook 定义于 connection.c ,它是一个由宏定义的文件级的变量。 

从 hook 到 run--宏的展开
展开 ap_hook_宏和 ap_run宏 
/**
 * 展开 apache2 的 ap_hook_宏和  ap_run宏
 * 使用 gcc -E -I/usr/local/apache2/include macos.h 可得到实际的c 代码
 * by fancp 2011-1-10 p_168@163.com
 * 
 **************************************************
*/
#include 
<ap_config.h>

APR_HOOK_STRUCT(
    APR_HOOK_LINK(create_request_bin)
)

AP_DECLARE_HOOK(
int,create_request_bin,(conn_rec *c, void *csd))


AP_IMPLEMENT_HOOK_RUN_ALL(
int, create_request_bin,
                          (request_rec_bin 
*r), (r), OK, DECLINED)

 



ap_filter_rec_t 数据结构
/***************************************
 * 
 * util_filter.h
 **************************************
*/
struct ap_filter_rec_t {
    
/** The registered name for this filter */
    
const char *name;

    
/** The function to call when this filter is invoked. */
    ap_filter_func filter_func;

    
/** The function to call directly before the handlers are invoked
     * for a request.  The init function is called once directly
     * before running the handlers for a request or subrequest.  The
     * init function is never called for a connection filter (with
     * ftype >= AP_FTYPE_CONNECTION).  Any use of this function for
     * filters for protocols other than HTTP is specified by the
     * module supported that protocol.
     
*/
    ap_init_filter_func filter_init_func;

    
/** The type of filter, either AP_FTYPE_CONTENT or AP_FTYPE_CONNECTION.  
     * An AP_FTYPE_CONTENT filter modifies the data based on information 
     * found in the content.  An AP_FTYPE_CONNECTION filter modifies the 
     * data based on the type of connection.
     
*/
    ap_filter_type ftype;

    
/** The next filter_rec in the list */
    
struct ap_filter_rec_t *next;

    
/** Providers for this filter */
    ap_filter_provider_t 
*providers;

    
/** Trace level for this filter */
    
int debug;

    
/** Protocol flags for this filter */
    unsigned 
int proto_flags;
};

 

 
/*
 * Read data from the next filter in the filter stack.  Data should be
 * modified in the bucket brigade that is passed in.  The core allocates the
 * bucket brigade, modules that wish to replace large chunks of data or to
 * save data off to the side should probably create their own temporary
 * brigade especially for that use.
 
*/
AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t 
*next,
                                        apr_bucket_brigade 
*bb,
                                        ap_input_mode_t mode,
                                        apr_read_type_e block,
                                        apr_off_t readbytes)
{
    
if (next) {
        
return next->frec->filter_func.in_func(next, bb, mode, block,
                                               readbytes);
    }
    
return AP_NOBODY_READ;
}

 

 
posted @ 2011-02-16 10:54  范晨鹏  阅读(609)  评论(0编辑  收藏  举报