Пример #1
0
static char *
ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
#if (NGX_HAVE_DLOPEN)
    void                *handle;
    char               **names, **order;
    ngx_str_t           *value, file;
    ngx_uint_t           i;
    ngx_module_t        *module, **modules;
    ngx_pool_cleanup_t  *cln;

    if (cf->cycle->modules_used) {
        return "is specified too late";
    }

    value = cf->args->elts;

    file = value[1];

    if (ngx_conf_full_name(cf->cycle, &file, 0) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    cln = ngx_pool_cleanup_add(cf->cycle->pool, 0);
    if (cln == NULL) {
        return NGX_CONF_ERROR;
    }

    handle = ngx_dlopen(file.data);
    if (handle == NULL) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           ngx_dlopen_n " \"%s\" failed (%s)",
                           file.data, ngx_dlerror());
        return NGX_CONF_ERROR;
    }

    cln->handler = ngx_unload_module;
    cln->data = handle;

    modules = ngx_dlsym(handle, "ngx_modules");
    if (modules == NULL) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
                           &value[1], "ngx_modules", ngx_dlerror());
        return NGX_CONF_ERROR;
    }

    names = ngx_dlsym(handle, "ngx_module_names");
    if (names == NULL) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
                           &value[1], "ngx_module_names", ngx_dlerror());
        return NGX_CONF_ERROR;
    }

    order = ngx_dlsym(handle, "ngx_module_order");

    for (i = 0; modules[i]; i++) {
        module = modules[i];
        module->name = names[i];

        if (ngx_add_module(cf, &file, module, order) != NGX_OK) {
            return NGX_CONF_ERROR;
        }

        ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%ui",
                       module->name, module->index);
    }

    return NGX_CONF_OK;

#else

    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                       "\"load_module\" is not supported "
                       "on this platform");
    return NGX_CONF_ERROR;

#endif
}
Пример #2
0
// 打开动态库文件
// 设置内存池销毁时的清理动作,关闭动态库
// 使用"ngx_modules"取动态库里的模块数组
// 使用"ngx_module_names"取动态库里的模块名字数组
// 使用"ngx_module_order"取动态库里的模块顺序数组
// 模块顺序只对http filter模块有意义
// 所以可以没有,不需要检查
// 遍历动态库里的模块数组
// 流程类似ngx_preinit_modules
// 调用ngx_add_module添加模块
static char *
ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
#if (NGX_HAVE_DLOPEN)
    void                *handle;
    char               **names, **order;
    ngx_str_t           *value, file;
    ngx_uint_t           i;
    ngx_module_t        *module, **modules;
    ngx_pool_cleanup_t  *cln;

    // 标志位,cycle已经完成模块的初始化,不能再添加模块
    if (cf->cycle->modules_used) {
        return "is specified too late";
    }

    // 取配置参数
    value = cf->args->elts;

    // 第一个参数是动态库文件名
    file = value[1];

    if (ngx_conf_full_name(cf->cycle, &file, 0) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    // 当cycle内存池销毁时的清理动作
    cln = ngx_pool_cleanup_add(cf->cycle->pool, 0);
    if (cln == NULL) {
        return NGX_CONF_ERROR;
    }

    // 打开动态库文件
    handle = ngx_dlopen(file.data);
    if (handle == NULL) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           ngx_dlopen_n " \"%s\" failed (%s)",
                           file.data, ngx_dlerror());
        return NGX_CONF_ERROR;
    }

    // 设置内存池销毁时的清理动作,关闭动态库
    cln->handler = ngx_unload_module;
    cln->data = handle;

    // 使用"ngx_modules"取动态库里的模块数组
    modules = ngx_dlsym(handle, "ngx_modules");
    if (modules == NULL) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
                           &value[1], "ngx_modules", ngx_dlerror());
        return NGX_CONF_ERROR;
    }

    // 使用"ngx_module_names"取动态库里的模块名字数组
    names = ngx_dlsym(handle, "ngx_module_names");
    if (names == NULL) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
                           &value[1], "ngx_module_names", ngx_dlerror());
        return NGX_CONF_ERROR;
    }

    // 使用"ngx_module_order"取动态库里的模块顺序数组
    // 模块顺序只对http filter模块有意义
    // 所以可以没有,不需要检查
    order = ngx_dlsym(handle, "ngx_module_order");

    // 遍历动态库里的模块数组
    // 流程类似ngx_preinit_modules
    // 调用ngx_add_module添加模块
    for (i = 0; modules[i]; i++) {
        module = modules[i];

        // 在这里为动态模块设置名字
        module->name = names[i];

        // cycle->modules_n是模块计数器 如果超过最大数量则报错
        // 使用模块里的各种信息进行检查,只有正确的才能加载
        // 首先是版本号,必须一致,例如1.10的不能给1.9使用
        // 比较签名字符串,里面是二进制兼容信息
        // 看cycle里的模块数组里是否有重名的 也就是说每个模块的名字都不能相同
        // 模块还没有加载,那么就给一个全局序号,不是ctx_index
        // 把动态模块的指针加入cycle的模块数组
        // 最后完成了一个动态模块的加载,放到了cycle模块数组里的合适位置
        if (ngx_add_module(cf, &file, module, order) != NGX_OK) {
            return NGX_CONF_ERROR;
        }

        ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%ui",
                       module->name, module->index);
    }

    return NGX_CONF_OK;

#else

    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                       "\"load_module\" is not supported "
                       "on this platform");
    return NGX_CONF_ERROR;

#endif
}