Apache文件加载流程

数据库 waitig 448℃ 百度已收录 0评论

我们使用Apache服务器时大多会自己开发新的模块用来进行数据传输,还会将自己定义的文件加入到服务中,这个过程相当于对Apache进行二次开发。
Apache的模块应该包括一个module对象,这里称呼对象不合适,因为C里面没有对象的概念,如下面这个,

  module AP_MODULE_DECLARE_DATA epgs_db_module =
   {
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    create_db_config,
    NULL,
    db_cmds,
    register_hooks
  }; 

Module是Apache定义的模块结构体,定义如下,

typedef struct module_struct module;
struct module_struct {
    /** API version, *not* module version; check that module is 
     * compatible with this version of the server.
     */
    int version;
    /** API minor version. Provides API feature milestones. Not checked 
     *  during module init */
    int minor_version;
    /** Index to this modules structures in config vectors.  */
    int module_index;

    /** The name of the module's C file */
    const char *name;
    /** The handle for the DSO.  Internal use only */
    void *dynamic_load_handle;

    /** A pointer to the next module in the list
     *  @defvar module_struct *next */
    struct module_struct *next;

    /** Magic Cookie to identify a module structure;  It's mainly 
     *  important for the DSO facility (see also mod_so).  */
    unsigned long magic;

    /** Function to allow MPMs to re-write command line arguments.  This
     *  hook is only available to MPMs.
     *  @param The process that the server is running in.
     */
    void (*rewrite_args) (process_rec *process);
    /** Function to allow all modules to create per directory configuration
     *  structures.
     *  @param p The pool to use for all allocations.
     *  @param dir The directory currently being processed.
     *  @return The per-directory structure created
     */
    void *(*create_dir_config) (apr_pool_t *p, char *dir);
    /** Function to allow all modules to merge the per directory configuration
     *  structures for two directories.
     *  @param p The pool to use for all allocations.
     *  @param base_conf The directory structure created for the parent directory.
     *  @param new_conf The directory structure currently being processed.
     *  @return The new per-directory structure created
     */
    void *(*merge_dir_config) (apr_pool_t *p, void *base_conf, void *new_conf);
    /** Function to allow all modules to create per server configuration
     *  structures.
     *  @param p The pool to use for all allocations.
     *  @param s The server currently being processed.
     *  @return The per-server structure created
     */
    void *(*create_server_config) (apr_pool_t *p, server_rec *s);
    /** Function to allow all modules to merge the per server configuration
     *  structures for two servers.
     *  @param p The pool to use for all allocations.
     *  @param base_conf The directory structure created for the parent directory.
     *  @param new_conf The directory structure currently being processed.
     *  @return The new per-directory structure created
     */
    void *(*merge_server_config) (apr_pool_t *p, void *base_conf, 
                                  void *new_conf);

    /** A command_rec table that describes all of the directives this module
     * defines. */
    const command_rec *cmds;

    /** A hook to allow modules to hook other points in the request processing.
     *  In this function, modules should call the ap_hook_*() functions to
     *  register an interest in a specific step in processing the current
     *  request.
     *  @param p the pool to use for all allocations
     */
    void (*register_hooks) (apr_pool_t *p);
};

这里补充一下:epgs_db_module里面STANDARD20_MODULE_STUFF是一个宏,它包含了一系列的参数,所以epgs_db_module看起来跟module定义不对齐,其实是对齐的。
这个数据结构很长 但是我们这里不需要全都看,跟文件加载相关的有两个,一个是函数,我们epgs_db_module里面是create_db_config,这个其实跟模块加载有关系,用来在模块加载时调用,另一个是command_rec,在加载文件时调用,这里我们epgs_db_module里面是db_cmds,我们在程序里定义了他

static const command_rec db_cmds[] = 
{
    AP_INIT_RAW_ARGS("DBPath", set_db_path, NULL, OR_FILEINFO,
    "配置DB数据集文件路径"),
    {NULL}
};

这里的参数DBPath就是用来标志哪个模块可以处理这个文件的,当我们读配置文件时,我们先把文件到一个链表中,当然这个链表中不只有文件数据也有其他的一些配置信息,这些信息都是与服务有关的,Apache会调用相关的模块进行处理,流程跟处理文件类似,读到链表中之后首先遍历这个链表,然后通过查找模块链表将对应的处理模块找出来,具体如下,

ap_str_tolower(dir);
ml = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING);
APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht,
                                 const void *key,
                                 apr_ssize_t klen)
{
    apr_hash_entry_t *he;
    he = *find_entry(ht, key, klen, NULL);
    if (he)
        return (void *)he->val;
    else
        return NULL;
}

找到模块之后就可以直接调用第二个参数,一个函数,就可以进行加载了。


本文由【waitig】发表在等英博客
本文固定链接:Apache文件加载流程
欢迎关注本站官方公众号,每日都有干货分享!
等英博客官方公众号
点赞 (0)分享 (0)