search
HomeBackend DevelopmentPHP Tutorialnginx source code study notes (20) - event module 1 - initialization

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
      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
  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 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 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
PHP Dependency Injection Container: A Quick StartPHP Dependency Injection Container: A Quick StartMay 13, 2025 am 12:11 AM

APHPDependencyInjectionContainerisatoolthatmanagesclassdependencies,enhancingcodemodularity,testability,andmaintainability.Itactsasacentralhubforcreatingandinjectingdependencies,thusreducingtightcouplingandeasingunittesting.

Dependency Injection vs. Service Locator in PHPDependency Injection vs. Service Locator in PHPMay 13, 2025 am 12:10 AM

Select DependencyInjection (DI) for large applications, ServiceLocator is suitable for small projects or prototypes. 1) DI improves the testability and modularity of the code through constructor injection. 2) ServiceLocator obtains services through center registration, which is convenient but may lead to an increase in code coupling.

PHP performance optimization strategies.PHP performance optimization strategies.May 13, 2025 am 12:06 AM

PHPapplicationscanbeoptimizedforspeedandefficiencyby:1)enablingopcacheinphp.ini,2)usingpreparedstatementswithPDOfordatabasequeries,3)replacingloopswitharray_filterandarray_mapfordataprocessing,4)configuringNginxasareverseproxy,5)implementingcachingwi

PHP Email Validation: Ensuring Emails Are Sent CorrectlyPHP Email Validation: Ensuring Emails Are Sent CorrectlyMay 13, 2025 am 12:06 AM

PHPemailvalidationinvolvesthreesteps:1)Formatvalidationusingregularexpressionstochecktheemailformat;2)DNSvalidationtoensurethedomainhasavalidMXrecord;3)SMTPvalidation,themostthoroughmethod,whichchecksifthemailboxexistsbyconnectingtotheSMTPserver.Impl

How to make PHP applications fasterHow to make PHP applications fasterMay 12, 2025 am 12:12 AM

TomakePHPapplicationsfaster,followthesesteps:1)UseOpcodeCachinglikeOPcachetostoreprecompiledscriptbytecode.2)MinimizeDatabaseQueriesbyusingquerycachingandefficientindexing.3)LeveragePHP7 Featuresforbettercodeefficiency.4)ImplementCachingStrategiessuc

PHP Performance Optimization Checklist: Improve Speed NowPHP Performance Optimization Checklist: Improve Speed NowMay 12, 2025 am 12:07 AM

ToimprovePHPapplicationspeed,followthesesteps:1)EnableopcodecachingwithAPCutoreducescriptexecutiontime.2)ImplementdatabasequerycachingusingPDOtominimizedatabasehits.3)UseHTTP/2tomultiplexrequestsandreduceconnectionoverhead.4)Limitsessionusagebyclosin

PHP Dependency Injection: Improve Code TestabilityPHP Dependency Injection: Improve Code TestabilityMay 12, 2025 am 12:03 AM

Dependency injection (DI) significantly improves the testability of PHP code by explicitly transitive dependencies. 1) DI decoupling classes and specific implementations make testing and maintenance more flexible. 2) Among the three types, the constructor injects explicit expression dependencies to keep the state consistent. 3) Use DI containers to manage complex dependencies to improve code quality and development efficiency.

PHP Performance Optimization: Database Query OptimizationPHP Performance Optimization: Database Query OptimizationMay 12, 2025 am 12:02 AM

DatabasequeryoptimizationinPHPinvolvesseveralstrategiestoenhanceperformance.1)Selectonlynecessarycolumnstoreducedatatransfer.2)Useindexingtospeedupdataretrieval.3)Implementquerycachingtostoreresultsoffrequentqueries.4)Utilizepreparedstatementsforeffi

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools