Home  >  Article  >  Backend Development  >  nginx source code study notes (20) - event module 1 - initialization

nginx source code study notes (20) - event module 1 - initialization

WBOY
WBOYOriginal
2016-07-29 09:11:01852browse

After reading the previous study notes, I believe that I have a certain understanding of the startup process of nginx. From this section on, we want to go deep into each module and learn the main operations within each module.

This article comes from: http://blog.csdn.net/lengzijian/article/details/7598996

Today we will learn about the event module. In the previous startup, we mentioned calling each module many times. The hook function of

This method mainly creates an ngx_event_conf_t structure and allocates memory space. nginx 源码学习笔记(二十)—— event 模块一 ——初始化

2. Read the configuration file:

For example, the read file has the following lines:

[cpp] view plaincopyprint?

events

{

use epoll;

  1. worker_connections 10240; }
  2. The events in this place are a block instruction. Many instructions can be configured within the brackets. These instructions are defined in src/event/ngx_event.c
  3. [cpp] view plaincopyprint?
static
ngx_command_t ngx_event_core_commands[] = {

{ ngx_string(
    "worker_ connections"
  1. ), NGX_EVENT_CONF|NGX_CONF_TAKE1,
  2. ngx_event_connections,
  3. 0, 0,
  4. NULL },
  5. ...(omitted here)
  6.                                                                                     
  7. NGX_EVENT_CONF|NGX_CONF_TAKE1,
  8. ngx_event_connections,
  9. 0,
  10. 0,
  11. NULL },
  12. {ngx_string(
  13. "use" ),
  14. NGX_EVENT_CONF|NGX_CONF_TAKE1,
  15. ngx_event_use,
  16. 0,
  17. 0,
  18. NULL },
  19. ngx_null_command
  20. };
  21. When events are parsed, the following function will be called back:
  22. [cpp] view plaincopyprint?
    1. src/event/ngx_event.c  
    2. static char *  
    3. ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)  
    4. {  
    5.     char                 *rv;  
    6.     void               ***ctx;  
    7.     ngx_uint_t            i;  
    8.     ngx_conf_t            pcf;  
    9.     ngx_event_module_t   *m;  
    10.   
    11.     /* count the number of the event modules and set up their indices */  
    12.     //计算event模块数量,并且记录  
    13.     ngx_event_max_module = 0;  
    14.     for (i = 0; ngx_modules[i]; i++) {  
    15.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {  
    16.             continue;  
    17.         }  
    18.   
    19.         ngx_modules[i]->ctx_index = ngx_event_max_module++;  
    20.     }  
    21.   
    22.     ctx = ngx_pcalloc(cf->pool, sizeof(void *));  
    23.     if (ctx == NULL) {  
    24.         return NGX_CONF_ERROR;  
    25.     }  
    26.     //为每一个event模块分配空间,用来保存响应配置结构的地址  
    27.     //共分配了ngx_event_max_module个空间  
    28.     *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));  
    29.     if (*ctx == NULL) {  
    30.         return NGX_CONF_ERROR;  
    31.     }  
    32.   
    33.     *(void **) conf = ctx;  
    34.   
    35.     for (i = 0; ngx_modules[i]; i++) {  
    36.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {  
    37.             continue;  
    38.         }
    39. m = ngx_modules[i]->ctx;
    40. ​​​​​
    41. if
    42. (m->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
    43.                                                                     
    44. ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {
    45.                                                                                                                                                  
    46. pcf = *cf; cf->ctx = ctx;
    47. cf->module_type = NGX_EVENT_MODULE;
    48. cf->cmd_type = NGX_EVENT_CONF;
    49. //Since events is a block instruction, many other instructions can be configured in the events domain,
    50. //For example, the use mentioned before, etc., now start to parse the instructions in the events block and complete the initialization Work.
    51. rv = ngx_conf_parse(cf, NULL);
    52. *cf = pcf;
    53. if (rv != NGX_CONF_OK)
    54.                                                                             
    55. ​​​​​​​​​​​
    56. if​(ngx_modules[i]-> ;type != NGX_EVENT_MODULE) {
    57.                                                        m = ngx_modules[i]->ctx;
    58. //Loop to execute each event The init_conf function of the module, the initialization configuration structure
    59. (m-& gt; init_conf) {
    60. RV = m-& gt; init_conf (CF-& GT; cycle, (*ctx) [ngx_modules[i]->ctx_index]); return
    61. rv;                          
    62. }
    63. return
    64. NGX_CONF_OK;
    65. }

      The most important process in the ngx_events_block() function is to call ngx_conf_parse(cf, NULL). The function of calling ngx_conf_parse() here is to complete the parsing of the events{} block in the configuration file, thereby calling all configurations under it. The callback function of the instruction completes the initialization of parsing the configuration file. But here I have a personal question. After asking the seniors, I will specify the question and answer******.

      2. Initialize conf (init_conf)

      ngx_event_init_conf()

      This method mainly initializes the ngx_event_conf_t structure.

      3.ngx_event_module_init

      As the name suggests, it is the initialization operation of the module, but looking at the source code of each module, it is found that many modules do not have init callback functions. I am also struggling with why here, hoping to find the answer after learning all the code.

      [cpp] view plaincopyprint?

      1. src/event/ngx_event.c  
      2. static ngx_int_t  
      3. ngx_event_module_init(ngx_cycle_t *cycle)  
      4. {  
      5.     void              ***cf;  
      6.     u_char              *shared;  
      7.     size_t               size, cl;  
      8.     ngx_shm_t            shm;  
      9.     ngx_time_t          *tp;  
      10.     ngx_core_conf_t     *ccf;  
      11.     ngx_event_conf_t    *ecf;  
      12.       
      13.     //判断ngx_events_module是否调用过初始化conf操作  
      14.     cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module);  
      15.   
      16.     if (cf == NULL) {  
      17.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,  
      18.                       "no "events" section in configuration");  
      19.         return NGX_ERROR;  
      20.     }  
      21.       
      22.     //获取ngx_event_core_module模块的配置结构  
      23.     ecf = (*cf)[ngx_event_core_module.ctx_index];  
      24.       
      25.     //查看是否是event中的模块,例如use 。。。。
      26. if (!ngx_test_config && ngx_process <= NGX_PROCESS_MASTER) {
      27. ngx_log_error(NGX _LOG_NOTICE, cycle->log, 0,
      28.                                                                              "event method", ecf->name);
      29. }
      30. //Get the configuration structure of the ngx_core_module module
      31. ccf = (ngx_core_conf_t *) ngx_get_conf(cycle- >conf_ctx, ngx_core_module);
      32. //Get the timer_resolution parameter from the configuration structure of the ngx_core_module module ngx_timer_resolution = ccf->timer_resolution;
      33. #if !(NGX_WIN32)
      34. { ngx_int_t limit;
      35. rlimit rlmt;
      36. //Get the ability of the current process The maximum number of open files man getrlimit
      37. (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { x_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      38.                                                                                                                                                                                                                        else{
      39. _The maximum number of connections to a module is unlimited​​
      40. ​​​​​/ /Or ngx_event_core_module connection is greater than ngx_core_module maximum number of connections
      41. (ECF-& GT; Connections & GT; (ngx_uint_t) rlmt.rlim_cur
      42. (ccf-& gt; _NOFILE == ngx_conf_unset
      43.                                                                limit = (ccf->rlimit_nofile == NGX_CONF_UNSET) ?
      44. ( ngx_int_t) rlmt.rlim_cur: ccf- & gt; rlimit_nofile;
      45.                                                                                 " open file resource limit: %i" ); endif /* !(NGX_WIN32) */
      46. //If the master process is closed, return
      47. //Because closing the master process means single-process work Method,
      48. //The subsequent operations create shared memory to implement locks and other work, which is not required for a single process.
    66. if (ccf->master == 0) {
    67. NGX_OK; }
    68. // If the accept mutex already exists, there is no need to create it again.
    69. NGX_OK;
    70. }
    71. /* cl should be equal or bigger than cache line size */
    72. cl = 128;
    73. //Create size here Shared memory, this shared memory will be divided into three equal segments
    74. size = cl                                      + cl                                                       
    75.                                                                                                       ,
    76. shm.size = size;
    77.  shm.name.len = sizeof("nginx_shared_zone"
    78. );
    79.  shm.name.data = (u_char *) "nginx_share d_zone"
    80. ;
    81. shm.log = cycle->log;
    82. (ngx_shm_alloc(&shm) ! = NGX_OK) { NGX_ERROR;
    83. NGX_ERROR;
    84. shared = shm.addr;
    85. //Accept mutex gets the first cl size memory of shared memory
    86. ngx_accept_mutex_ptr = (ngx_atomic_t *) shared; ngx_accept_mutex.spin = (ngx_uint_t) -1;
    87. /*Create accept mutex
    88. The implementation of accept mutex depends on whether it supports atomic operations, if there are corresponding atomic operations;
    89. That’s it Use the obtained shared memory to implement the accept mutex; otherwise, the file lock will be used to implement the accept mutex.
    90. The function of the accept mutex is to avoid panic groups and achieve load balancing of worker processes.
  23. ngx_accept_mutex, shared, cycle->lock_file.data)
  24. != NGX_OK)
  25.                                                                                     
  26. //Get the cl-sized address of the second segment of memory
  27. ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl);
  28. (
  29. void
  30. ) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);
  31. ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle- >log, 0,
  32.                                                                                                         x_connection_counter);
  33. //Get the size of the third segment of memory cl Address
  34. ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl);
  35. tp = ngx_timeofday() ;
  36. ngx_random_number = (tp-> ;msec << 16) + ngx_pid;
  37. return
  38. NGX_OK;
  39. 4.ngx_event_process_init in the previous worker process As mentioned in the analysis, when a worker process is created, the worker process will first initialize the process, and at this time the ngx_event_process_init function will be called.
  40. [cpp] view plaincopyprint?
    1. src/event/ngx_event.c
    2. staticngx_int_t
    3. ngx_event_process_init(ngx_cycle_t *cycle)
    4. {
    5. ngx_uint_t m, i;
    6. ngx_event_t *rev, *wev;
    7. ngx_listening_t *ls;
    8. ngx_connection_t *c, *next, *old;
    9. ngx_core_conf_t *ccf;
    10. ngx_event_conf_t *ecf;
    11. ngx_event_module_t *module;
    12. //As before, get the configuration structure of the response module
    13. ccf = (ngx_core_conf_t *) ngx_get_conf( cycle->conf_ctx, ngx_core_module);
    14.  ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
    15. //Master process is open, worker process is greater than 1, accept_mutex has been created
    16. //cai Open the accept mutex
    17. if (ccf->master &&ccf->worker_processes > 1 &&ecf->accept_mutex) {
    18. ngx_use_accept_mutex = 1; / /Use mutex
    19. ngx_accept_mutex_held = 0; //Whether to get accept mutex
    20. ngx_accept_mutex_delay = ecf->accept_mutex_delay;//After failure to compete for the mutex , waiting for the next scramble time interval
    21. } else {
    22. ngx_use_accept_mutex = 0 ;
    23. }
    24. #if (NGX_THREADS)
    25. //Threads aside
    26. #endif
    27. //Initialize counter, a red will be created here Black Tree, to maintain the timer, will explain in detail later
    28. if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
    29. return NGX_ERROR;
    30. }
    31. for (m = 0; ngx_modules[m]; m++) {
    32. //As mentioned here before, skip non-NGX_EVENT_MODULE modules
    33.                                                                                                                                                               
    34. }
    35.                                      // Modules specified by non-use configuration instructions are skipped, Linux default epoll                                              ->use) { module = ngx_modules[m]->ctx;
    36. /*Call the init function of the specific time module ( These modules are located in the src/event/modules directory), so nginx A layer of abstraction has been made to the time module, which makes it easier for different systems to use different event models and expands new time models. Our focus should be on epoll.
    37.                                                                                                                                                                                                                 The init callback here actually calls the ngx_epoll_init function. The module->actions structure encapsulates all interface functions of epoll. nginx registers epoll into the event abstraction layer through the actions structure.
    38. The type of actions is ngx_event_action_t, located in src/event/ngx_event.h
    39. These specific contents will be explained in the next section.
    40.                                        module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
    41. *fatal */
    42. exit(2); break
    43. ;
    44. }
    45. //Omitted here Part of the content
    46. //Create a global ngx_connection_t array to save all connections
    47. //Since this process is executed in each worker process, each worker has Own connection array
    48. cycle->connections = ngx_alloc(sizeof
    49. (ngx_connection_t) *cycle->connection_n, cycle->log);
    50. if
    51. (cycle->connections == NULL) {
    52. c = cycle->connections;
    53. //Create an array of read events
    54. cycle->read_events = ngx_alloc(sizeof
    55. (ngx_event_t) * cycle->connection_n,                                                                                                                                                                                                                                                                        ​;log);
    56. if
    57. (cycle->read_events == NULL) {
    58. NGX_ERROR;
    59. }
    60. rev = cycle->read_events;
    61. for (i = 0; i < cycle->connection_n; i++) {
    62. rev[i].closed = 1 ;
    63.                                  [i].instance = 1;
    64. #if (NGX_THREADS)
    65. rev[i].lock = &c[i].lock;
    66. rev[i].own_lock = &c[i].lock;
    67. #endif
    68. }  
    69.     //创建一个写事件数组  
    70.     cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,  
    71.                                     cycle->log);  
    72.     if (cycle->write_events == NULL) {  
    73.         return NGX_ERROR;  
    74.     }  
    75.   
    76.     wev = cycle->write_events;  
    77.     for (i = 0; i < cycle->connection_n; i++) {  
    78.         wev[i].closed = 1;  
    79. #if (NGX_THREADS)  
    80.         wev[i].lock = &c[i].lock;  
    81.         wev[i].own_lock = &c[i].lock;  
    82. #endif  
    83.     }  
    84.   
    85.     i = cycle->connection_n;  
    86.     next = NULL;  
    87.     //初始化整个connection数组  
    88.     do {  
    89.         i--;  
    90.   
    91.         c[i].data = next;  
    92.         c[i].read = &cycle->read_events[i];  
    93.         c[i].write = &cycle->write_events[i];  
    94.         c[i].fd = (ngx_socket_t) -1;  
    95.   
    96.         next = &c[i];  
    97.   
    98. #if (NGX_THREADS)  
    99.         c[i].lock = 0;  
    100. #endif  
    101.     }while (i);
    102. cycle->free_connections = next;
    103. cycle->free_connection_n = cycle-> connection_n;
    104. /* for each listening socket */
    105. //Assign a connection from the connection array for each listening socket, that is, a slot
    106. ls = cycle->listening .els; Connect to solt
    107. _ C = ngx_get_connection (ls [i] .fd, cycle-& gt; log); NGX_ERROR; }  
    108.   
    109.         c->log = &ls[i].log;  
    110.   
    111.         c->listening = &ls[i];  
    112.         ls[i].connection = c;  
    113.   
    114.         rev = c->read;  
    115.   
    116.         rev->log = c->log;  
    117.         rev->accept = 1; //读时间发生,调用accept  
    118.   
    119. #if (NGX_HAVE_DEFERRED_ACCEPT)  
    120.         //省略  
    121. #endif  
    122.   
    123.         if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {  
    124.             if (ls[i].previous) {  
    125.   
    126.                 /* 
    127.                  * delete the old accept events that were bound to 
    128.                  * the old cycle read events array 
    129.                  */  
    130.   
    131.                 old = ls[i].previous->connection;  
    132.   
    133.                 if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT)  
    134.                     == NGX_ERROR)  
    135.                 {  
    136.                     return NGX_ERROR;  
    137.                 }  
    138.   
    139.                 old->fd = (ngx_socket_t) -1;  
    140.             }  
    141.         }
    142. //Register the callback function ngx_event_accept
    143. rev->handler = ngx_even t_accept;
    144.                                    , do not put the listening socket into epoll for the time being, but
    145.                                                                                                                          {
    146.                                                                                                                                                                                                                                     
    147. }
    148. } else{
    149.      //If the accept mutex is not used, then put this listening socket into epoll.
    150.                                                                                                                                                                             
    151. #endif
    152. }
    153. return
    154. NGX_OK;
    155. }
    156. Until now , event-driven initialization has been completed.
    157. The above introduces the nginx source code study notes (20) - event module 1 - initialization, including IOC and counter content. I hope it will be helpful to friends who are interested in PHP tutorials.
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn