nginx源码阅读(十).ngx_event_core_module模块

前言

本小节将进入到ngx_event_core_module模块,它是所有事件模块中排第一位的模块,因为要负责创建连接池,还要选择I/O多路复用机制等工作。接下来我们就来看看它是如何做到的,以及在nginx中扮演了一个什么角色。

模块的通用接口

我们先来看看ngx_event_core_module模块实现的所有模块都需要实现的ngx_module_t接口。

ngx_module_t  ngx_event_core_module = {
    /* NGX_MODULE_V1定义为:
     * #define NGX_MODULE_V1      0, 0, 0, 0, 0, 0, 1
     * 直接初始化前7个成员
     */
    NGX_MODULE_V1,
    /* ctx成员,事件模块的具体化接口 */
    &ngx_event_core_module_ctx,            /* module context */
    //ngx_command_t成员
    ngx_event_core_commands,               /* module directives */
    //模块类型
    NGX_EVENT_MODULE,                      /* module type */
    NULL,                                  /* init master */
    //初始化ngx_event_core_module模块
    ngx_event_module_init,                 /* init module */
    //在进入到工作循环前进行初始化
    ngx_event_process_init,                /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    /* 将预留空间填充为0 */
    NGX_MODULE_V1_PADDING
};

关于ngx_event_module_init方法,在进入到master进程工作循环前由ngx_init_cycle调用:

//调用所有模块的init_module方法
for (i = 0; ngx_modules[i]; i++) {
    if (ngx_modules[i]->init_module) {
        if (ngx_modules[i]->init_module(cycle) != NGX_OK) {
            /* fatal */
            exit(1);
        }
    }
}

ngx_event_module_init所做的工作主要是初始化了一些变量,这里不具体分析(因为跟一些用于统计的变量有关,与该模块的联系不是特别大)

关于ngx_event_process_init,其实上一小节我们已经分析了它是如何创建连接池、读事件、写事件,不过除此之外,它还做了其他事情,比如调用指定的I/O多路复用机制模块的init方法。
关于它的调用,它是在ngx_worker_process_init中被调用。从main函数开始的调用栈如图:
这里写图片描述
而其的源码如下:

static ngx_int_t
ngx_event_process_init(ngx_cycle_t *cycle)
{
    ngx_uint_t           m, i;
    ngx_event_t         *rev, *wev;
    ngx_listening_t     *ls;
    ngx_connection_t    *c, *next, *old;
    ngx_core_conf_t     *ccf;
    ngx_event_conf_t    *ecf;
    ngx_event_module_t  *module;

    //获取ngx_core_module的配置项结构体指针
    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
    //获取ngx_event_core_module的配置项结构体指针
    ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);

    /* 当配置文件中的负载均衡锁的选项启用
     * 并且使用的是多进程模型(worker进程数大于1并且使用了master进程)
     * 于是开启accept_mutex负载均衡锁(代表需要进行负载均衡)
     */
    if (ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex) {
        //将全局负载均衡锁开关置为1
        ngx_use_accept_mutex = 1;
        //ngx_accept_mutex_held为0代表表示当前进程未获取到负载均衡锁
        //为1代表获取到了
        ngx_accept_mutex_held = 0;
        //ngx_accept_mutex_delay的值为在配置文件中指定的最大延迟时间
        //具体所代表的含义,我们在后面分析进程间负载均衡的时候再去了解
        ngx_accept_mutex_delay = ecf->accept_mutex_delay;

    } else {
        //否则将该全局变量置为0
        //表示不启用负载均衡(毕竟只有一个进程)
        ngx_use_accept_mutex = 0;
    }

#if (NGX_THREADS)
    ngx_posted_events_mutex = ngx_mutex_init(cycle->log, 0);
    if (ngx_posted_events_mutex == NULL) {
        return NGX_ERROR;
    }
#endif

    //初始化定时器(nginx中的定时器是由红黑树实现的)
    if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
        return NGX_ERROR;
    }

    //遍历所有事件模块
    for (m = 0; ngx_modules[m]; m++) {
        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
            continue;
        }

        //配置项中的use选项选择了使用的I/O多路复用机制
        //找到事件模块中的该事件驱动模块
        if (ngx_modules[m]->ctx_index != ecf->use) {
            continue;
        }

        module = ngx_modules[m]->ctx;

        //调用该模块对应的init方法进行初始化
        if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
            /* fatal */
            exit(2);
        }

        break;
    }

#if !(NGX_WIN32)

    /* nginx中采用了时间缓存,并不是需要获取时间时就调用gettimeofday来获取
     * 因此精度方面可能需要进行控制
     * 而ngx_timer_resolution(通过核心模块的配置项获取,默认是0)表示时间的精度
     * 而NGX_USE_TIMER_EVENT在epoll中并没有使用
     * 因此只要设置了控制时间的精度
     * 就会定期进行更新
     */
    if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
        /* 设置SIGALRM捕捉之后的处理函数
         
cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I ../modules/nginx-client-module -I ../modules/nginx-multiport-module -I ../modules/nginx-toolkit-module -I src/core -I src/event -I src/event/modules -I src/os/unix -I ../modules/nginx-rtmp-module -I objs -I src/http -I src/http/modules -I ../modules/nginx-rtmp-module -I ../modules/nginx-rtmp-module/http -I ../modules/nginx-rtmp-module/hls -I ../modules/nginx-rtmp-module/mpegts \ -o objs/src/http/ngx_http_parse.o \ src/http/ngx_http_parse.c cc1: all warnings being treated as errors make[1]: *** [objs/Makefile:995: objs/src/event/ngx_event_openssl.o] Error 1 make[1]: *** Waiting for unfinished jobs.... make[1]: Leaving directory '/home/ubuntu/pingos-master/nginx' make: *** [Makefile:8: build] Error 2 make -f objs/Makefile install make[1]: Entering directory '/home/ubuntu/pingos-master/nginx' cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I ../modules/nginx-client-module -I ../modules/nginx-multiport-module -I ../modules/nginx-toolkit-module -I src/core -I src/event -I src/event/modules -I src/os/unix -I ../modules/nginx-rtmp-module -I objs \ -o objs/src/event/ngx_event_openssl.o \ src/event/ngx_event_openssl.c src/event/ngx_event_openssl.c: In function ‘ngx_ssl_load_certificate_key’: src/event/ngx_event_openssl.c:722:9: error: ‘ENGINE_by_id’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 722 | engine = ENGINE_by_id((char *) p); | ^~~~~~ In file included from src/event/ngx_event_openssl.h:22, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:336:31: note: declared here 336 | OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_by_id(const char *id); | ^~~~~~~~~~~~ src/event/ngx_event_openssl.c:731:9: error: ‘ENGINE_load_private_key’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 731 | pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0); | ^~~~ In file included from src/event/ngx_event_openssl.h:22, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:638:11: note: declared here 638 | EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, | ^~~~~~~~~~~~~~~~~~~~~~~ src/event/ngx_event_openssl.c:735:13: error: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 735 | ENGINE_free(engine); | ^~~~~~~~~~~ In file included from src/event/ngx_event_openssl.h:22, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:493:27: note: declared here 493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e); | ^~~~~~~~~~~ src/event/ngx_event_openssl.c:739:9: error: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 739 | ENGINE_free(engine); | ^~~~~~~~~~~ In file included from src/event/ngx_event_openssl.h:22, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:493:27: note: declared here 493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e); | ^~~~~~~~~~~ src/event/ngx_event_openssl.c: In function ‘ngx_ssl_dhparam’: src/event/ngx_event_openssl.c:1335:5: error: ‘PEM_read_bio_DHparams’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 1335 | dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); | ^~ In file included from /usr/include/openssl/ssl.h:36, from src/event/ngx_event_openssl.h:15, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/pem.h:469:1: note: declared here 469 | DECLARE_PEM_rw_attr(OSSL_DEPRECATEDIN_3_0, DHparams, DH) | ^~~~~~~~~~~~~~~~~~~ src/event/ngx_event_openssl.c:1345:5: error: ‘DH_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 1345 | DH_free(dh); | ^~~~~~~ In file included from /usr/include/openssl/dsa.h:51, from /usr/include/openssl/x509.h:37, from /usr/include/openssl/ssl.h:31, from src/event/ngx_event_openssl.h:15, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/dh.h:204:28: note: declared here 204 | OSSL_DEPRECATEDIN_3_0 void DH_free(DH *dh); | ^~~~~~~ src/event/ngx_event_openssl.c: In function ‘ngx_ssl_error’: src/event/ngx_event_openssl.c:3066:13: error: ‘ERR_peek_error_line_data’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 3066 | n = ERR_peek_error_line_data(NULL, NULL, &data, &flags); | ^ In file included from src/event/ngx_event_openssl.h:16, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/err.h:425:15: note: declared here 425 | unsigned long ERR_peek_error_line_data(const char **file, int *line, | ^~~~~~~~~~~~~~~~~~~~~~~~ src/event/ngx_event_openssl.c: In function ‘ngx_ssl_session_ticket_key_callback’: src/event/ngx_event_openssl.c:3976:9: error: ‘HMAC_Init_ex’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 3976 | if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1) { | ^~ In file included from /usr/include/openssl/ssl.h:37, from src/event/ngx_event_openssl.h:15, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/hmac.h:43:27: note: declared here 43 | OSSL_DEPRECATEDIN_3_0 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, | ^~~~~~~~~~~~ src/event/ngx_event_openssl.c:4020:9: error: ‘HMAC_Init_ex’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 4020 | if (HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL) != 1) { | ^~ In file included from /usr/include/openssl/ssl.h:37, from src/event/ngx_event_openssl.h:15, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/hmac.h:43:27: note: declared here 43 | OSSL_DEPRECATEDIN_3_0 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, | ^~~~~~~~~~~~ src/event/ngx_event_openssl.c: In function ‘ngx_openssl_engine’: src/event/ngx_event_openssl.c:5151:5: error: ‘ENGINE_by_id’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 5151 | engine = ENGINE_by_id((char *) value[1].data); | ^~~~~~ In file included from src/event/ngx_event_openssl.h:22, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:336:31: note: declared here 336 | OSSL_DEPRECATEDIN_3_0 ENGINE *ENGINE_by_id(const char *id); | ^~~~~~~~~~~~ src/event/ngx_event_openssl.c:5159:5: error: ‘ENGINE_set_default’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 5159 | if (ENGINE_set_default(engine, ENGINE_METHOD_ALL) == 0) { | ^~ In file included from src/event/ngx_event_openssl.h:22, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:708:27: note: declared here 708 | OSSL_DEPRECATEDIN_3_0 int ENGINE_set_default(ENGINE *e, unsigned int flags); | ^~~~~~~~~~~~~~~~~~ src/event/ngx_event_openssl.c:5164:9: error: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 5164 | ENGINE_free(engine); | ^~~~~~~~~~~ In file included from src/event/ngx_event_openssl.h:22, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:493:27: note: declared here 493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e); | ^~~~~~~~~~~ src/event/ngx_event_openssl.c:5169:5: error: ‘ENGINE_free’ is deprecated: Since OpenSSL 3.0 [-Werror=deprecated-declarations] 5169 | ENGINE_free(engine); | ^~~~~~~~~~~ In file included from src/event/ngx_event_openssl.h:22, from src/core/ngx_core.h:83, from src/event/ngx_event_openssl.c:9: /usr/include/openssl/engine.h:493:27: note: declared here 493 | OSSL_DEPRECATEDIN_3_0 int ENGINE_free(ENGINE *e); | ^~~~~~~~~~~ cc1: all warnings being treated as errors make[1]: *** [objs/Makefile:995: objs/src/event/ngx_event_openssl.o] Error 1 make[1]: Leaving directory '/home/ubuntu/pingos-master/nginx' make: *** [Makefile:11: install] Error 2
最新发布
06-09
### Nginx 编译中与 OpenSSL 3.0 相关的弃用函数错误修复 在使用 OpenSSL 3.0 编译 Nginx 时,可能会遇到一些由于 OpenSSL 3.0 弃用某些函数(如 `ENGINE_by_id` 和 `ENGINE_load_private_key`)导致的编译错误。这是因为在 OpenSSL 3.0 中,这些函数已被标记为废弃,并且推荐使用新的接口来替代它们[^1]。 为了修复这些问题,可以采取以下方法: #### 方法一:修改 Nginx 源码以兼容 OpenSSL 3.0 Nginx源码中可能仍然使用了 OpenSSL 2.x 或更早版本中的函数。需要手动修改 Nginx 源码以适配 OpenSSL 3.0 的新接口。以下是具体的步骤和代码示例: 1. 找到 Nginx 源码中调用废弃函数的位置。例如,在 `ngx_ssl.c` 文件中,可能会有类似以下的代码: ```c ENGINE *e = ENGINE_by_id("dynamic"); if (e != NULL) { ENGINE_load_private_key(e, key_file, ui_method, pass); ENGINE_free(e); } ``` 2. 将上述代码替换为 OpenSSL 3.0 推荐的新接口。例如: ```c OSSL_PROVIDER *provider = OSSL_PROVIDER_load(NULL, "default"); EVP_KEYMGMT *keymgmt = EVP_KEYMGMT_fetch(NULL, "RSA", NULL); EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); if (provider && keymgmt && ctx) { EVP_PKEY *pkey = NULL; EVP_PKEY_fromdata_init(ctx); EVP_PKEY_fromdata(ctx, &pkey, keymgmt, key_data); // 继续处理 pkey } OSSL_PROVIDER_unload(provider); EVP_KEYMGMT_free(keymgmt); EVP_PKEY_CTX_free(ctx); ``` 这段代码展示了如何使用 OpenSSL 3.0 的新接口加载私钥[^1]。 3. 修改完成后,重新编译 Nginx。确保编译选项中正确指定了 OpenSSL 3.0 的路径,例如: ```bash ./configure --with-openssl=/path/to/openssl-3.0 --with-http_ssl_module make make install ``` #### 方法二:降级 OpenSSL 版本 如果暂时无法修改 Nginx 源码,可以选择降级 OpenSSL 到 1.1.x 版本。虽然这不是长期解决方案,但在紧急情况下可以作为权宜之计。安装 OpenSSL 1.1.x 的命令如下: ```bash yum install -y openssl11 openssl11-devel ``` #### 方法三:等待官方更新 Nginx 官方团队正在逐步适配 OpenSSL 3.0。建议关注 Nginx 的最新版本发布,因为未来版本可能已经内置对 OpenSSL 3.0 的支持[^1]。 ### 注意事项 - 在修改 Nginx 源码时,请确保备份原始文件,以便在出现问题时能够快速恢复。 - 如果使用第三方模块(如 ngx_http_vhost_traffic_status_module),也需要检查这些模块是否兼容 OpenSSL 3.0。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值