首頁  >  文章  >  後端開發  >  nginx 原始碼學習筆記(二十)—— event 模組一 ——初始化

nginx 原始碼學習筆記(二十)—— event 模組一 ——初始化

WBOY
WBOY原創
2016-07-29 09:11:01906瀏覽

讀完之前的學習筆記,相信已經對nginx的啟動流程有了一定的認識,從這一節起我們想深入各個模組,學習各個模組的內的主要操作。

本文來自於:http://blog.csdn.net/lengzijian/article/details/7598996

今天我們就來學習下event模組,在之前的啟動裡多次提到了各個模組的鉤子函數,我們先來回想一下關於event模組鉤子函數的執行,也是event模組啟動的步驟:

nginx 源码学习笔记(二十)—— event 模块一 ——初始化

1.創建韎

該方法,主要是創建了一個ngx_event_conf_t結構體,並且分配記憶體空間。

2.讀取設定檔:

例如讀取的檔案有如下行:

[cpp] view plaincopyprint?

events   
  1. {  
  2.   use oll; ;  
  3. }  
  4. 這個地方的events是block指令,在大括號內可以配置很多指令,這些指令定義在src/event/ngx_event.c中
[cpp] view plaincopyprint?

static

 ngx_command_t  ngx_event_core_commands[] = {  

x_string(

"worker_connections"
    ),  
  1.       NGX_EVENT_CONF|NGX_CONF_TAKE1,    NGX_EVENT_CONF|NGX_CONF_TAKE1,    NGX_EVENT_CONF|NGX_CONF_TAKE1,    NGX_EVENT_CONF|NGX_CONF1KE1,   s,
  2.       0,  
  3.       0,                   ...(此處省略)    
  4. .
  5.       NGX_EVENT_CONF|NGX_CONF_TAKE1,  
  6.     0,  
  7.       0,  
  8.         { ngx_string("use"
  9. ),  
  10.       NGX_EVENT_CONF|NGX_CONF_TAKE1,        0,  
  11.       0,     ull_command  
  12. };  
  13. 當解析到events是會回呼如下函數:
  14. [cpp] view plaincopyprint?
    1. src/event/ngx_event.c  
    2. static  ngx_conf_t *cf , ngx_command_t *cmd, void *conf)  
    3. {      char
    4.            無效
    5.                ***ctx;  
    6.     ngx_conf_t            pcf;  
    7. _   m;    
    8.     /*統計事件模組的數量並設定其索引*/
    9.   
    10.     ngx_event_max_module = 0;  
    11.     
    12. for
    13.  (i = 0; ngx_modules[i]; i++)  (ngx_modules[i]->type != NGX_ EVENT_MODULE) {  
    14.             繼續;  
    15.         }  
    16.           ngx_modules[i]->ctx_index = ngx_event_max_module++;  
    17.     }    
    18.     ctx = ngx_pcalloc(cf-> pool, sizeof(void
    19.  *));  
    20.            
    21. return
    22.  NGX_CONF_ERROR;  
    23.  
    24.     
    25. //每個事件模組分配空間,用於保存回應配置結構的位址  
    26.       *ctx = ngx_pcalloc( cf->pool, ngx_event_max_module * sizeof(
    27. void
    28.  *));   {  
    29.         
    30. return NGX_CONF_ERROR;  
    31.     }  
    32.   
    33.       
    34.     for (i = 0; ngx_modules[i]; i++ ) {  
    35.         if  (ngx_modules[i]-          繼續;  
    36.         }
    37.   
    38.         m = ngx_modules[i]-dx _conf鉤子函數,用於建立設定結構
    39.   
    40.         if
    41.  (m->create_conf) {  
    42.             ,*)[             
    43. if
    44.  ((*ctx )[ngx_modules[i]->ctx_index] == NULL) {  
    45.                       }  
    46.      
    47. pcf = *cf;  
    48.     cf->ctx = ctx;  
    49.       cf->cmd_type = NGX_EVENT_CONF;  
    50.     
    51. //由於events為block指令,events域下方還可以設定許多其他指令,  
    52.     
    53. //例如之前提起的use等,現在開始解析events block中的指令,完成工作初始化。   
    54.     rv = ngx_conf_parse(cf, NULL);  
    55.   
    56.       if
    57.  (rv != NGX_CONF_OK) 
    58.         return rv;  
    59.     = 0; ngx_modules[i]; i++) {  
    60.         
    61. if
    62.  (ngx_modul (ngx_modul. type != NGX_EVENT_MODULE) {  
    63.             
    64.   }  
    65.         m = ngx_modules[i]->ctx;    init_conf函數,初始化配置結構  
    66.         if      rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i] ->ctx_index]);  
    67.             if
    68.  (rv            
    69. return rv;  
    70.        }  
    71.     }  
    72.   
    73.     return NGX_CONF_OK;  

    74. ngx_events_block()函數中最重要的一個過程就是呼叫ngx_conf_parse(cf, NULL),此處呼叫ngx_conf_parse()的作用就是完成設定檔中events{}這個block的解析,從而呼叫其下所有的設定檔指令的回呼函數,完成解析設定檔的初始化工作。但這裡我個人有個問題,待問完前輩之後,在指明問題和答案******。

      2.初始化conf(init_conf)

      ngx_event_init_conf()

      該方法,主要是初始化ngx_event_conf_t結構體。

      3.ngx_event_module_init

      從名字上看是模組的初始化操作,但是縱觀各個模組原始碼,發現很多模組都沒有init回呼函數。這裡本人也在糾結為什麼,希望在學完全部代碼後,能找到答案。

      [cpp] view plaincopyprint?

      1. src/event/ngx_event.c  
      2. static ngx_int_t   
      3. {  
      4.     無效
      5.      
      6.     u_char              *共享;  
      7.     size_t
      8.                尺寸, cl;  
      9.     ngx_shm_t            shm;  
      10.     ngx_time_t          *tp;  
      11.     ngx_core_conf_t     *ccf;  
      12.     ngx_event_conf_t *ecf;  
      13.       
      14.     //  = ngx_get_conf(cycle->conf_ctx, ngx_事件模組);  
      15.        if
      16.  (cf == NULL) {  
      17.   
      18.                       「設定中沒有「事件」部分」); 「配置中沒有「事件」部分」); 
      19.         
      20.  NGX_ERROR;     
      21.       //取得ngx_event_core_module模組的設定結構
      22.   
      23.     ecf = (cf.
      24.           //檢視是否為event中的模組,例如使用。 。 。 。  
    75.     if (!ngx_test_config && ngx_process        ngx_log_error(NGX_LOG_NOTICE, cycle->script  0,  
    76.       event method", ecf->name);  
    77.     }  
    78.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);  
    79.           //將
    80.     ngx_timer_resolution = ccf->timer_resolution;  
    81.   
    82. #if ! (NGX_WIN32)  
    83.     {  
    84.   
    85. struct
    86.  rlimit  rlmt;  
    87.       拾取man getrlimit
    88.   
    89.     if
    90.  (getrlimit       ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,  
    91.      RLIMIT_NOFILE) failed, ignored");  
    92.   
    93.  }  else {  
    94.         //如果     //且ngx_core_module最大連線數無限制  
    95.        /或ngx_event_core_module連線數大於ngx_core_module最大連線數  
    96.                      && (ccf->rlimit_nofile == NGX_CONF_UNSET
    97.                 || ecf->connections > (ngx_uint_t) ccf->親素
    98.             limit = (ccf->rlimit_nofile == NGX_CONF_UNSET          (ngx_int_t) rlmt.rlim_cur : ccf ->rlimit_nofile;    
    99.                                       
    100. "%ui worker_connections are                      
    101. "open file resource limit: %i",  
    102.                           ecf->connections, limit);  
    103.         }  
    104.     }  
    105.     }  
    106. #endif /* !(NGX_WIN32) */   
    107.   
    108.     //如果關閉了master進程,就返回是單一工作方式,  
    109.     
    110. //之後的操作時建立共享記憶體實作鎖等工作,單進程不需要。  
    111.     if (ccf->master == 0) {   NGX_OK;  
    112.     }       已經有accept互斥了,不需要再重複創建了
    113.   
    114.     if
    115.  (ngx_accept_mutex_ptrif (ngx_accept_mutex_ptr))   return NGX_OK;  
    116.     }  
    117.   
    118.     
    119. /* cl should be equal or bigger   
    120.     cl = 128;  
    121.     //在這裡創造sizeize大小的大小的大小共享內存,這塊共享記憶體將被分成三段
    122.       size = cl       
    123.            + cl          /* 
    124.            + cl;         
    125. /* ngx_temp_number */    //準備共享內存,大小為size,命名nginx_shared_zone,
    126.       shm.size 
    127.     shm.size     shm.size     
    128.     shm.name.len = sizeof("nginx_shared_zone"
    129. ); *) 
    130. "nginx_shared_zone";  
    131.     shm .log = cycle->log;  
    132.       
    133.         if (ngx_shm_alloc(&shm) != NGX_OK ) {  
    134.         
    135. return NGX_ERROR;      //取得起始位址保存      shared = shm.addr; 
    136.     //accept互斥體取得共享記憶體的第一段cl大小記憶體  
    137.        ngx_accept_mutex.spin = (ngx_uint_t) -1;  
    138.     
    139. /*創建accept互斥體
    140.       
    141.  
    142.     就是使用的這段共享記憶體來實現accept互斥體;否則,將使用檔案鎖定 
    143.     來實現accept互斥體。  
    144.      
    145.     accept 互斥體的作用是:避免驚群與實現worker進程的負載平衡。 
    146.      
    147.     */  (ngx_shmtx_create(&ngx_accept_mutex, shared, cycle->lock_file.data)  
    148.        {          
    149. return
    150.  
    151.       Sharp ngx_atomic_t *) (shared + 1 * cl);  
    152.   
    153.   , 1);  
    154.   
    155.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT,   ngx_log_debug2(NGX_LOG_DEBUGcleEVENT, cycy-> log, 0,  
    156.                                    ngx_connection_counter, *ngx_connection_counter);     ngx_connection_counter, *ngx_connection_counter);     
    157.     ngx_temp_number = (ngx_atomic_t *) (shared + 2    tp = ngx_timeofday();  
    158.   
    159.     ngx_   
    160.     
    161. return
    162. 4.ngx_event_process_init在先前的worker進程分析中有提到過,當創建了一個worker進程後,worker進程首先就會做進程的初始化工作,此時會呼叫ngx_event_process_init函數。
    163. [cpp] view plaincopyprint?
      1. src/event/ngx_event.c  
      2. static ngx_int_t o_p )  
      3. {  
      4.     ngx_uint_t         ngx_event_t         *rev, *wev;  
      5.     ngx_listening_t      *c, *next, *old;  
      6.     ngx_core_conf_t     *ccf;  
      7.     ngx_event_module_t *module;  
      8.       
      9.     //與先前相同,取得反應模組 (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);  
      10.     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);  
      11.    ,已經創建了accept_mutex
      12.   
      13.     //才打開accept互斥體  
      14.     if
      15.  (ccf->master && ccf->worker_processes 
      16.         ngx_use_accept_mutex = 1; //使用互斥物
      17.   
      18.         ngx_accept_mutex_held = 0;   ngx_accept_mutex_delay = ecf->accept_mutex_delay;//爭搶互斥體失敗後,等待下次爭搶時間間隔  
      19.       }  ngx_use_accept_mutex = 0;  
      20.     }    
      21.     //先未講  
      22. #endif器,此處將會建立一顆紅黑樹,來維護計時器,之後會詳細解說  
      23.     if (ngx_event_timer_init       
      24. return
      25.  NGX_ERROR;  
      26.     }      }  
      27.     for
      28.  (m = 0; ngx_modules[m]; m++) {   NGX_EVENT_MODULE模組
      29.   
      30.         if (ngx_modules[m]->type != NGX_EVENT_MODULE) {  
      31.                 }
      32.         //非use配置指令指定的模組跳過,linux預設epoll   es[m]->ctx_index != ecf->use) {  
      33.             continue;  
      34.          module = ngx_modules[m]->ctx;  
      35.               
      36.         由於nginx實現了許多事件模組     (這些模組位於src/event/modules目錄中),所以nginx對時間模組進行了一層抽象,
      37.  
      38.         方便了不同的系統使用不同的事件模型,也方便擴充新的時間模型,我們的重點應該 
      39.          
      40.     _  module->actions結構封裝了 
      41.         epoll的所有介面函數。 nginx就是透過actions結構將epoll註冊到事件抽象層。  
      42.         actions的種類是ngx_event_action_t,位於src/event/ngx_event.h 
      43.         這些特定的內容會在下一節中重點解說。 
      44.          
      45.         */  
      46.         if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {  
      47.             /* fatal */  
      48.             exit(2);    
      49.         
      50. break
      51. ;  
      52. 內容  
      53.     
      54. //創建全域的ngx_connection_t數組,保存所有的connection worker進程中執行的,所以每個worker都有自己的connection陣列
      55.       cycle->connections =  
      56. t) * cycle->connection_n, cycle->log);  
      57.     if
      58.  ( cycle->connections == NULL) {  
      59.         return
      60.   
      61.     c = cycle->connections;  🎠 //建立一個讀取事件陣列  
      62.     cycle->read_events = ngx_alloc(size 🠎(ngx_event_t)                                 if
      63.  (cycle->read_events == NULL) {             }  
      64.   
      65.     rev = cycle->read_events;  for
      66.  (i = 0; i connection_n; i++) {  
      67.         rev[i].instance = 1;  
      68. #if (NGX_THREADS)  
      69.         rev[i].lock = own_lock = &c[i].lock;  # endif
      70.   
      71.     }
      72.     //建立一個寫事件佇列  
      73.    cycle->connection_n,                      
      74.     
      75. if
      76.  (cycle->write_events == NULL) {   OR;  
      77.     }    
      78. cle.
      79.     for
      80.  (i = 0; i 連接_n; i++) {  = 1;  
      81. #if (NGX_THREADS)   
      82.         wev[i].lock = &c[i].lock;   
      83. #endif  
      84.     }  
      85.   
      86.     i = 循環-
      87.     //初始化連接佇列  
      88.     
      89. do
      90.     
      91. do
      92.     
      93.         i--;  
      94.   
      95.         c[i].read = &cycle->read_events[i];  
      96.         c [i].write = &cycle->write_events[i];  
      97.         c[i].fd = (ngx_socket_t)  c[i].fd = (ngx_socket_t)  c[i].fd = (ngx_socket_t)  c
      98.         下一個= &c[i];  
      99.   
      100. #if (NGX_THREADS)
      101.   
      102. #endif
      103.   
      104.     }while (i);  
      105.   
      106.     ->free_connection_n = cycle->connection_n;  
      107.   
      108.     /* forforforforforforforfor號each listening socket */
      109.       //每個監聽套接字從一個接合🠎 ls = cycle->listening.elts;  
      110.     for (i = 0; i listening.nelts; i++) {  在ton中取得新的連線solt
      111.   
      112.         c = ngx_get_connection(ls[i].fd, cycle->log);    
      113.                 return
      114.  NGX_ERROR;  
      115.  NGX_ERROR;  
      116. }
      117.   
      118.         c->log = &ls[i].log;    c->聽= &ls[i];  
      119.         ls[i].connection = c ;  
      120.   
      121.         rev = c->閱讀;  ->log = c->log;  
      122.         rev->accept = 1; //讀取時間問    
      123. //簡潔
      124.   
      125. #endif
      126.   
      127.         if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) & NGX_USE_
      128. IOC
      129. P_EVENT))      if
      130.  (ls[i].previous) {  
      131.    
      132.                 * 刪除舊的接受事件綁定     * 舊循環讀取事件陣列 
      133.                                 的舊式 = ls [i].previous->連接;    
      134.              NGX_CLOSE_EVENT)  
      135.                            {                        回復
      136.  NGX_ERR或;    }    
      137.                            }  
      138.         }
      139.   
      140.         //登錄監聽套介面毒事件的回呼函數   rev->handler = ngx_event_accept;            
      141. 暫時不將監聽套接字放入epoll中,而是
      142.   
      143.         
      144. //worker
      145.         if (ngx_use_accept_mutex) {  
      146.             continue;  
      147.         }            
      148.                   if
      149.  (ngx_event_flags & NGX_USE_RTSIG_EVENT) {  
      150.             if
      151.  (ngx_add_conn(c) == NGX_ERROR)      
      152. return NGX_ERROR;  
      153.                  } else {  
      154.             //沒有使用accept互斥體,因此將此監聽套接字放入epoll中。   
      155.             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {  
      156.                 
      157. return NGX_ERROR;  
      158.             }  
      159.         }  
      160.   
      161. #endif  
      162.   
      163.     return NGX_OK;  
      164. }  
      165. }  ,事件驅動的初始化已經完成。
      166. 以上就介紹了nginx 原始碼學習筆記(二十)—— event 模組一 ——初始化,包括了IOC,計數器方面的內容,希望對PHP教程有興趣的朋友有所幫助。
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn