Nginx source Reading (10). Ngx_event_core_module Module

Source: Internet
Author: User
Tags bind epoll thread

General interface of the preface module A general interface summary of the configuration item storage configuration item Event module of interest

Preface

This section goes into the Ngx_event_core_module module, which is the first module in all event modules because it is responsible for creating the connection pool and choosing the I/O multiplexing mechanism. Next we'll look at how it's done and what role it plays in Nginx. common interface for modules

Let's take a look at the ngx_module_t interface that all modules implemented by the Ngx_event_core_module module need to implement.

ngx_module_t ngx_event_core_module = {/* NGX_MODULE_V1 defined as: * #define NGX_MODULE_V1 0, 0, 0, 0, 0, 0, 1 * Direct initialization of the first 7 members */NGX_MODULE_V1,/* CTX Members, event module materialization interface */&ngx_event_core_modu LE_CTX,/* Module context *///ngx_command_t member Ngx_event_core_commands,/* Module DIRECTI                                  VES *//modules type Ngx_event_module,/* Module-type */NULL, /* Init Master *//Initialize Ngx_event_core_module module Ngx_event_module_init,/* init modules *///On entry to Initialize Ngx_event_process_init,/* init process */NULL,/* INI before working cycle T thread */NULL,/* EXIT thread */NULL,/* Exi T process */NULL,/* Exit Master */* fills the reserved space with 0 */ngx_module_v1_padding}; 

About the Ngx_event_module_init method, called by Ngx_init_cycle before entering the work cycle of the master process:

Call the Init_module method for all modules 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);}
}

The main task of Ngx_event_module_init is to initialize a number of variables, which are not specifically analyzed (because it is related to some variables used for statistics, the connection to the module is not particularly large)

About Ngx_event_process_init, in fact, we've analyzed how it creates connection pools, read events, write events, but in addition, it does other things, such as invoking the Init method of the specified I/O multiplexing mechanism module.
About its invocation, it is called in Ngx_worker_process_init. The call stack starting from the main function is shown in figure:

and its source code is as follows:

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;
    Gets the Ngx_core_module configuration item struct pointer CCF = (ngx_core_conf_t *) ngx_get_conf (cycle->conf_ctx, ngx_core_module);

    Get ngx_event_core_module configuration item struct pointer ECF = ngx_event_get_conf (Cycle->conf_ctx, ngx_event_core_module);  /* When the option to load Balancer lock in the profile is enabled * and is using a multi-process model (the number of worker processes is greater than 1 and the master process is used) * then turn on the Accept_mutex load Balancer Lock (representing the need for load balancing) */IF (Ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex)
        {//Reset the global load Balancer lock switch to 1 Ngx_use_accept_mutex = 1;
        Ngx_accept_mutex_held for 0 indicates that the current process has not been acquired to the load Balancer lock//for 1 to obtain the Ngx_accept_mutex_held = 0;
    The value of Ngx_accept_mutex_delay is the maximum delay time specified in the configuration file//The meaning that we are going to look at later when we analyze load balancing between processes.    Ngx_accept_mutex_delay = ecf->accept_mutex_delay;
    } else {///otherwise the global variable is set to 0//to indicate that load balancing is not enabled (after all, only one process) 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//Initialize timer (the timer in Nginx is implemented by red-black tree) if (ngx_event_timer_init (cycle->log) = = Ngx_error) {return ngx_
    ERROR;
            }//Traverse all event modules for (m = 0; ngx_modules[m]; m++) {if (Ngx_modules[m]->type! = ngx_event_module) {
        Continue }//The Use option in the configuration item selects the I/O multiplexing mechanism used//Find the event driver module in the event module if (ngx_modules[m]->ctx_index! = ecf->use)
        {continue;

        } module = ngx_modules[m]->ctx; Call the module corresponding to the Init method to initialize if (Module->actions.init (cycle, ngx_timer_resolution)! = NGX_OK) {/* fatal *
        /exit (2);
    } break; } #if!
(NGX_WIN32)
    /* The time cache is used in Nginx, it is not necessary to get time to call Gettimeofday to get * so the accuracy may need to control * and ngx_timer_resolution (through the core module configuration items obtained by default is 0) indicates The precision of time * and ngx_use_timer_event is not used in Epoll * so as long as the control time is set the accuracy * will be updated periodically */if (Ngx_timer_resolution & amp;&! (Ngx_event_flags & Ngx_use_timer_event))
        {/* Set the handler function after SIGALRM capture * ngx_timer_signal_handler */struct sigaction sa;

        struct Itimerval ITV;
        Ngx_memzero (&sa, sizeof (struct sigaction));
        Sa.sa_handler = Ngx_timer_signal_handler;

        Sigemptyset (&sa.sa_mask);
                          if (Sigaction (SIGALRM, &sa, NULL) = =-1) {Ngx_log_error (Ngx_log_alert, Cycle->log, Ngx_errno,
            "Sigaction (SIGALRM) failed");
        return ngx_error; }/* Set timing time * It_interval member specifies the time of the interval * It_value member specifies initial timing time */itv.it_interval.tv_
        SEC = ngx_timer_resolution/1000; Itv.it_interval.tv_usec = (ngx_tImer_resolution% 1000) * 1000;
        Itv.it_value.tv_sec = ngx_timer_resolution/1000;

        itv.it_value.tv_usec = (ngx_timer_resolution% 1000) * 1000; /* Call the Setitimer function * Every ngx_timer_resolution time call the Ngx_timer_signal_handler method */if (Setitimer (itimer_
                          REAL, &ITV, NULL) = =-1) {Ngx_log_error (Ngx_log_alert, Cycle->log, Ngx_errno,
        "Setitimer () failed");

        }/* Use poll event driver */if (Ngx_event_flags & ngx_use_fd_event) {struct Rlimit rlmt;
                          if (Getrlimit (rlimit_nofile, &RLMT) = =-1) {Ngx_log_error (Ngx_log_alert, Cycle->log, Ngx_errno,
            "Getrlimit (Rlimit_nofile) failed");
        return ngx_error;

        } Cycle->files_n = (ngx_uint_t) rlmt.rlim_cur;
                                  /* pre-allocating a handle used by the runtime */cycle->files = Ngx_calloc (sizeof (ngx_connection_t *) * cycle->files_n, Cycle->log);
        if (cycle->files = = NULL) {return ngx_error; }} #endif/* Pre-allocated Connections array */cycle->connections = Ngx_alloc (sizeof (ngx_connection_t) * cycle
    ->connection_n, Cycle->log);
    if (cycle->connections = = NULL) {return ngx_error;

    } C = cycle->connections;
                                   /* Pre-allocated Read event */cycle->read_events = Ngx_alloc (sizeof (ngx_event_t) * Cycle->connection_n,
    Cycle->log);
    if (cycle->read_events = = NULL) {return ngx_error;
    }/* Initialize Read event */Rev = cycle->read_events;
        for (i = 0; i < cycle->connection_n; i++) {rev[i].closed = 1;
Rev[i].instance = 1;
        #if (ngx_threads) Rev[i].lock = &c[i].lock;
Rev[i].own_lock = &c[i].lock;
                                    #endif}/* Pre-allocated Write event */cycle->write_events = Ngx_alloc (sizeof (ngx_event_t) * Cycle->connection_n,
    Cycle->log); If (cycle->write_events = = NULL)
    {return ngx_error;
    }/* Initialize write event */Wev = cycle->write_events; for (i = 0; i < cycle->connection_n; i++) {wev[i].closed = 1; #if (ngx_threads) Wev[i].lock = &
        C[i].lock;
Wev[i].own_lock = &c[i].lock; #endif}/* When initializing state, the connections array is an idle connection * Use the data variable to concatenate all elements of the connections array * and bind the read and write events to the connection * and
    Set FD to 1 */i = cycle->connection_n;

    Next = NULL;

        do {i--;
        C[i].data = Next;
        C[i].read = &cycle->read_events[i];
        C[i].write = &cycle->write_events[i];

        C[I].FD = (ngx_socket_t)-1;

Next = &c[i];
#if (ngx_threads) c[i].lock = 0;

    #endif} while (i);
    Point Free_connections to the first idle connection cycle->free_connections = Next;

    Set number of idle connections cycle->free_connection_n = cycle->connection_n; /* For each listening socket */* Assigns a connection to each listening port */ls = cycle->listEning.elts; for (i = 0; i < cycle->listening.nelts; i++) {/* Get an idle connection */c = ngx_get_connection (LS[I].FD, CYCL

        E->log);
        if (c = = NULL) {return ngx_error;

        } C->log = &ls[i].log;
        Bind an listening object to a Connection object c->listening = &ls[i];

        Binds the connection object to the Listening object ls[i].connection = C;

        Listening port only cares about Read Events Rev = c->read;
        Rev->log = c->log;

Set to can accept connection rev->accept = 1;
#if (ngx_have_deferred_accept) rev->deferred_accept = ls[i].deferred_accept; #endif if (! ( Ngx_event_flags & Ngx_use_iocp_event) {if (ls[i].previous) {/* * dele

                Te the old accept events, were bound to * the old cycle Read Events array */

                Old = ls[i].previous->connection;
  if (Ngx_del_event (Old->read, ngx_read_event, ngx_close_event)                  = = Ngx_error) {return ngx_error;
            } OLD-&GT;FD = (ngx_socket_t)-1; }} #if (Ngx_win32) if (Ngx_event_flags & ngx_use_iocp_event) {ngx_iocp_conf_t *iocpcf

            ;

            Rev->handler = Ngx_event_acceptex;
            if (Ngx_use_accept_mutex) {continue;
            } if (Ngx_add_event (rev, 0, ngx_iocp_accept) = = Ngx_error) {return ngx_error;

            } Ls[i].log.handler = Ngx_acceptex_log_error;
            IOCPCF = ngx_event_get_conf (Cycle->conf_ctx, ngx_iocp_module);
                if (Ngx_event_post_acceptex (&ls[i], iocpcf->post_acceptex) = = Ngx_error) {
            return ngx_error;

            }} else {rev->handler = ngx_event_accept;
            if (Ngx_use_accept_mutex) {continue;

   }         if (Ngx_add_event (rev, ngx_read_event, 0) = = ngx_error) {return ngx_error; }} #else/* Set the Accept connection callback function as Ngx_event_accept * that is, the callback function when the connection request is received on the listening port * in the Ngx_event_accept function from the connected Access to the connection in the pool * key operations: Ls->handler (c);

        Invoke other event consumption module handler (such as HTTP module) */Rev->handler = ngx_event_accept;
            /* If load balancing is used (Ngx_use_accept_mutex is 1) * Only add event to Epoll when a load balancer lock is available */if (Ngx_use_accept_mutex) {
        Continue
                } if (Ngx_event_flags & ngx_use_rtsig_event) {if (Ngx_add_conn (c) = = Ngx_error) {
            return ngx_error;
                }} else {//To add a read event to the Epoll listener event if (Ngx_add_event (rev, ngx_read_event, 0) = = ngx_error) {
            return ngx_error;
}} #endif} return NGX_OK; }

configuration items of interest

Before analyzing the materialized universal interface Ngx_event_core_module_ctx of the event module, we first understand which modules are interested in the Ngx_event_core_module module, which is helpful for us to understand the code behind.

Static ngx_command_t ngx_event_core_commands[] = {///connection pool size, that is, the number of TCP maximum connections supported per worker process//is the same as the following connections configuration item {ngx_string ("worker_connections"), ngx_event_conf| Ngx_conf_take1, ngx_event_connections, 0, 0, NULL},//size of connection pool {ngx_string ("connections") , ngx_event_conf| Ngx_conf_take1, ngx_event_connections, 0, 0, NULL},//determines which event module is selected as the I/O multiplexing mechanism {Ngx_stri Ng ("use"), ngx_event_conf| Ngx_conf_take1, Ngx_event_use, 0, 0, NULL},//For Epoll, this configuration item means that when a new connection event is received, the call Accpet as much as possible to accept the connected Connect {ngx_string ("multi_accept"), ngx_event_conf| Ngx_conf_flag, Ngx_conf_set_flag_slot, 0, Offsetof (ngx_event_conf_t, multi_accept), NULL},/ /Determine whether to use Load Balancer Lock, default is on//But after the nginx1.11.3 version, the default is to close {ngx_string ("Accept_mutex"), ngx_event_conf|
Ngx_conf_flag, Ngx_conf_set_flag_slot, 0, Offsetof (ngx_event_conf_t, Accept_mutex), NULL},
    After you enable the load Balancer lock, delay accept_mutex_delay milliseconds before attempting to process the new connection event {ngx_string ("Accept_mutex_delay"), ngx_event_conf| 

    Ngx_conf_take1, Ngx_conf_set_msec_slot, 0, Offsetof (ngx_event_conf_t, Accept_mutex_delay), NULL}, You need to print debug logs of debug level {ngx_string ("debug_connection") to the TCP connection from the specified IP, ngx_event_conf| Ngx_conf_take1, ngx_event_debug_connection, 0, 0, NULL}, Ngx_null_command};

As mentioned before, the Ngx_init_cycle function calls Ngx_conf_parse to parse the nginx.conf file, which invokes Ngx_conf_handler, iterating through the Ngx_modules array with the configuration item read sequentially. If a module is interested in the configuration item, it is called by the function set in its commands member to process the configuration item.
Here we summarize a little bit about the parsing of configuration items in the event module and the storage aspects.

The first is to call the Ngx_conf_parse function in the Ngx_init_cycle function, where the Ngx_conf_handler function is called, the Ngx_modules array is traversed on the read configuration item, and when read to "events{}", Ngx_ Events_module calls the function Ngx_events_block that the set member points to in the commands member, internally requesting the structure space of the storage configuration item and contacting the CONF_CTX of the core structure ngx_cycle_t

The structure of the storage configuration item already has, Ngx_events_block calls the Ngx_conf_parse, when has the event module to be interested in the configuration item, will call the current event module set of configuration item resolution method (corresponding to the above listed 7 configuration items of interest)

The last call to each module will implement the INIT_CONF value set to the default value in the corresponding configuration item struct body.

The corresponding init_conf method in the Ngx_event_core_module module is the ngx_event_init_conf function, and we will analyze the function below. After parsing the configuration file, members that are not yet assigned in the configuration item structure will be set to the default value, which is the work of ngx_event_init_conf. Storage Configuration Items

So now we can see what the structure of the configuration items stored in the event module looks like (as defined in event/ngx_event.h):

typedef struct {
    //connection pool size
    ngx_uint_t    connections;
    /* The event-driven module selected
     here is stored inside the module in the event module */
     ngx_uint_t use    ;

    /* Identity bit, 1 indicates when a new connection event is received, create as many connections as possible at once */
    ngx_flag_t    multi_accept;
    /* Identity bit, 1 means enable load balancer Lock */
    ngx_flag_t    Accept_mutex;

    /* Load balancer Lock causes some worker processes to delay establishing a new connection when the lock is not reached
     * and the delay is performed by Accept_mutex_delay (in MS) *
     /
    ngx_msec_t    Accept_mutex_delay;

    Select the name of the event-driven module, which corresponds to the use member
    U_char       *name;

#if (ngx_debug)
    ngx_array_t   debug_connection;
#endif
} ngx_event_conf_t;
common interface for event modules
......
Static ngx_str_t  event_core_name = ngx_string ("Event_core");

......
ngx_event_module_t  ngx_event_core_module_ctx = {
    //name
    &event_core_name,
    //create_conf
    ngx_event_create_conf,/                 * Create configuration */
    //init_conf
    ngx_event_init_conf,/                   * init Configuration */

    * for methods in Ngx_event_actions Ngx_event_core_module does not need to be implemented
     * Because the module does not need to register, add, delete, and other operations
     */
    {null, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};

Let's take a look at how ngx_event_create_conf is implemented:

static void *
ngx_event_create_conf (ngx_cycle_t *cycle)
{
    ngx_event_conf_t  *ecf;

    Request the structure body (ngx_event_conf_t) space of the storage configuration item
    ECF = Ngx_palloc (cycle->pool, sizeof (ngx_event_conf_t));
    if (ECF = = null) {
        return null;
    }

    Set the members of the configuration item structure Body (ngx_event_conf_t) to UNSET
    ecf->connections = ngx_conf_unset_uint;
    Ecf->use = Ngx_conf_unset_uint;
    ecf->multi_accept = Ngx_conf_unset;
    Ecf->accept_mutex = Ngx_conf_unset;
    Ecf->accept_mutex_delay = ngx_conf_unset_msec;
    Ecf->name = (void *) Ngx_conf_unset;

#if (Ngx_debug)

    if (Ngx_array_init (&ecf->debug_connection, Cycle->pool, 4,
                       sizeof (Ngx_event_ debug_t) = = Ngx_error)
    {
        return NULL;
    }

#endif

    return ECF;
}

Only look at the function of the source code is not enough, mainly to grasp the function for what function is called, when called, so as to the logic of the event module clear, otherwise understand the code does not understand why do this.

The ngx_event_create_conf function is called in Ngx_events_block, and it invokes the Create_conf function (the ngx_event_create_conf function) of all event modules before parsing the configuration file , you first request space to store the configuration item structure (ngx_event_conf_t), and then you set the members of the struct to Ngx_conf_unset (this is not the default, but not set).

The Ngx_events_block then invokes Ngx_conf_parse to parse the configuration item and store it in the struct (ngx_event_conf_t)

After parsing the configuration file, call the Ngx_event_init_conf method to set the member in the configuration item structure that is not set to the default value.

Static char * ngx_event_init_conf (ngx_cycle_t *cycle, void *conf) {//Gets the configuration item pointer to the module ngx_event_conf_t *ECF = conf; #if (ngx_have_epoll) &&!
(ngx_test_build_epoll) int fd;
    #endif #if (Ngx_have_rtsig) ngx_uint_t Rtsig;
ngx_core_conf_t *CCF;
    #endif ngx_int_t i;
    ngx_module_t *module;

    ngx_event_module_t *event_module;

module = NULL; #if (ngx_have_epoll) &&!


    (ngx_test_build_epoll)/* Call Epoll_create to test whether the Epoll mechanism is available */fd = epoll_create (100); if (FD! =-1) {/* Create successful, prove Epoll available * Close Test epoll return FD * Select Epoll as default Event driver module */close
        (FD);

    module = &ngx_epoll_module;
         } else if (ngx_errno! = Ngx_enosys) {/* Although the return-1 creation failed * But if errno is not Enosys (Function not implemented)
    * Prove that Epoll is still available (at least the current machine has this mechanism exists) */module = &ngx_epoll_module; } #endif/* If there is a rtsig mechanism and module is not selected * Then the RTSIG mechanism is used by default */#if (NGX_HAVE_RTSIG) if (module = = NULL) {module = &ngx_rtsig_module;

    Rtsig = 1;
    } else {rtsig = 0;  } #endif/* If there is a devpoll mechanism, select the Devpoll mechanism * Here you may wonder why it is not necessary to determine if the module is null * because there is currently no mechanism for Epoll, Devpoll, Kqueue and so on on one operating system */#if

(ngx_have_devpoll) module = &ngx_devpoll_module;

#endif/* If there is a kqueue mechanism, the kqueue mechanism is selected by default */#if (ngx_have_kqueue) module = &ngx_kqueue_module; #endif/* If module is not selected * Select is selected by default */#if (Ngx_have_select) if (module = = NULL) {module = &n
    Gx_select_module; } #endif/* Go to this step, if the module is still not selected * then traverse the event module, select the first non-ngx_event_core_module module as the default event driver module */if (module = = NULL) {for (i = 0; ngx_modules[i]; i++) {//filter out non-event module if (Ngx_modules[i]->type! = Ngx
            _event_module) {continue;

            } Event_module = ngx_modules[i]->ctx; Filter out Ngx_event_core_module Module I

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.