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捕捉之后的处理函数
         * ngx_timer_signal_handler
       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值