首頁 >後端開發 >php教程 >nginx 原始碼學習筆記(二十一)- event 模組二 -事件驅動核心ngx_process_events_and_timers

nginx 原始碼學習筆記(二十一)- event 模組二 -事件驅動核心ngx_process_events_and_timers

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

首先繼續回憶下,之前子執行緒執行操作裡面有一個未涉及的內容ngx_process_events_and_timers,今天我們就來研究下這個函數。

這篇文章來自於:http://blog.csdn.net/lengzijian/article/details/7601730

先來看看第十九節

nginx 源码学习笔记(二十一)—— event 模块二 ——事件驱动核心ngx_process_events_and_timers
今天主要講解的就是事件驅動函數,圖中的紅色部分:

[cpppp plaincopyprint?

  1. src/event/ngx_event.c  
  2.   
  3. timers(ngx_cycle_t *cycle)  {  
  4.     ng
  5.     ngx_msec_t  timer, delta;  
  6.   
  7.   
  8.         timer = NGX_TIMER_INFINITE;  
  9.     
  10.     } else  {  
  11.         timer = ngx_event_find_timer();  _TIME;  
  12.     }  
  13.           ngx_use_accept_mutex變數代表是否使用accept互斥體
  14.  
  15.     預設使用,可透過accept_mutex off;指令關閉; 
  16.     */
  17.     
  18. if
  19.  (ngx_use_accept_mutex) {           
  20. /*
  21.  
  22.         ngx_accept_disabled變數在ngx_event_accept函數中計算。
  23.  
  24.         如果ngx_accept_disabled大於0,並表示此程序接受的連結過多,
  25.  同時將自己減一。  
  26.         然後,並繼續處理已連結上的事件。  
  27.         nginx利用這一點實現了繼承關於連接的基本負載平衡。          */
  28.    0) {  
  29.             ngx_accep t_disable  else
  30.  {  
  31.             
  32. /* 
  33.     
  34.             因此,而確保了只有一個程序擁有監聽套接口,故   才不會驚群現象。 
  35.             */    (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {  
  36.                      }  
  37.                if
  38.  (ngx_accept_mutex_held) {   
  39. /* 
  40.                 
  41.  
  42.           ‧  
  43.                 因為,以處理時間可能會很耗時,且不先施放鎖、除霸鎖             導致其他流程無法取得鎖定,且有accept的效率就低了。  
  44.                 */     flags |= NGX_POST_EVENTS;  
  45.       
  46.                 /* 
  47.    所得進程,當然不需要NGX_POST_EVENTS標誌。  
  48.                 但為要設定延遲時多久,且再去爭搶。 
  49.                 */     if
  50.  (timer == NGX_TIMER_INFINITE  
  51.          
  52.                 {   accept_mutex_delay;  
  53.                 }  
  54.             }  
  55.         }  
  56.     }  
  57.   
  58.     delta = ngx_current_msec;  
  59.       
  60.     
  61. /*接下來,epoll要開始wait事件,
  62.  
  63.     ngx_process_events的具體實作是對應epoll模組中的ngx_epoll_process_events函數 之後🠎
  64.     */  
  65.     (void
  66. ) ngx_process_events(cycle, timer, flags);  
  67.      delta = ngx_current_msec - delta;  
  68.       ngx_log_debug1 (NGX_LOG_DEBUG_EVENT, cycle->log, 0,  
  69.                  
  70.     
  71. /*
  72.  
  73. post
  74. 佇列,暫存epoll從監聽套介面wait到的accept事件。
  75.  
  76.     前文提到的NGX_POST_EVENTS標誌使用後,將所有的accept事件暫存到這個隊列
  77.  
  78.     if (ngx_posted_accept_events ) {  
  79.         ngx_event_process_posted(cycle, &ngx_posted_accept_eventH);     //所有accept事件處理完後,如果持有鎖的話,就釋放掉。  
  80.     if (ngx_accept_mutex_held) &ngx_accept_mutex);  
  81.     }  
  82.           delta是之前統計的耗時,存在毫秒級的耗時,就對所有時間的timer進行檢查,
  83.  
  84.     如果timeout 就從time rbtree中刪除到期的timer,同時調用相應事件的handler函數處理相應事件的handler函數處理?     */
  85.   
  86.     
  87. if (delta) {  
  88.         ngx_event_expire_timers();      }  
  89.       ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle-> log, 0,  
  90.                    》,ed 
  91.   
  92.     
  93. /* 
  94.     處理普通事件中所獲得的寫字事件),
  95.  
  96.     因為每個事件都有自己的handler方法, 
  97.    if
  98.  (ngx_posted_events) {  
  99.         
  100. if  (ngx_threaded) {  
  101.             ngx_wakeup_worker_thread(cycle);  
  102.   
  103.         } else {  
  104.             ngx_event_process_posted(cycle, &ngx_posted_events);  
  105.         }  
  106. }  
  107. }  
  108. 之前有說過accept事件,其實他就是監聽套介面上是否有新來的事件,下面介紹下accept時間的
  109. [cpp] view plaincopyprint?
    1. src/event/ngx_event_accept.c  
    2.   
    3. void x_event_t * ev)  
    4. {  
    5.     socklen_t     
    6.     ngx_err_t           ngx_socket_t       s;  
    7.     ngx_event_t         *ls;  
    8.     ngx_connection_t  *c, *lc;  
    9.     ngx_event_conf_t  *ecf;  
    10.     u_char          
    11.     //省略部分代碼
    12.    
    13.     ls = lc->聽;  
    14.     ev->準備=0;  bug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,  
    15.               , 準備:%d"
    16. ,&ls->addr_text,ev->可用);  
    17.            socklen = NGX_SOCKADDRLEN;  
    18.         / /接受一個新的連線
    19.   
    20.         s = accept(lc->fd, (
    21.         
    22. //簡潔部分程式碼  
    23.           
    24.         
    25.  重新計算ngx_accept_disabled的值,           主要是為了做負載平衡,且之前有提及。
    26.  
    27.                    「連接數八分之一   -   剩餘的連結數「
    28.  
    29.        指每個行程設定的再最大連線數,這個數字可以設定檔中指定。
     
  110.          
  111.     
  112.          
  113.         
  114.         ngx_accept_disabled                        - ngx_cycle->free_connection_n;          
  115. //取得connection
  116.   
  117.         c= ngx_get_connection(s, ev->log);  
  118.   
  119.                //連接關閉的時候,才釋放pool
  120.   
  121.         c->pool =     if (c->pool == NULL) {  
  122. ngx_close_accepted_connection(c);              return🎠 
  123.   
  124.         c->sockaddr = ng   if
  125.  (c->sockaddr == NULL) {              ngx_close_accepted_connection(c);  
  126.             return
  127. ;          }  
  128.   
  129.         ngx_memcpy(c->sockaddr , sa, socklen);  
  130.   
  131.         log         if
  132.  (log == NULL) {  
  133.             ngx_close_accepted_connection(c);    
  134.         }
  135.   
  136.         /* 為aio設定阻塞模式,並設定非阻塞模式        if
  137.  (ngx_inherited_nonblocking) {  
  138. if (ngx_event_flags & NGX_USE_AIO_EVENT) {  
  139.      == -1) {                       
  140.                                  
  141. 「失敗」);  
  142.                                    
  143. 回復;  
  144.                }  
  145.   
  146.  
  147.  {  
  148.             //我們使用epoll      if
  149.  (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) {                  if
  150.  (ngx_nonblocking(s) ==         ngx_log_error(NGX_LOG_ALERT, ev-> ;log, ngx_socket_errno,  
  151.          ngx_nonblocking_n 
  152. 「失敗」);  
  153.                     ngx_close_accepted_connection(c);  🎠  ;  
  154.                 
  155.         }
  156.   
  157.         *log = ls->log;   
  158.         c->recv = ngx_recv;  
  159.   ngx_send;  
  160.         c->recv_chain = ngx_recv_chain;  
  161.  
  162.   
  163.         c->log = log;  = log;  
  164.   
  165.         c->socklen = s   
  166.         c->local_sockaddr = ls->sockaddr;    
  167.   
  168.         c->unexpected_eof = 1;  
  169.   
  170. 🎠         
  171. if
  172. (c->sockaddr->sa_家 == AF_UNIX) {  
  173.             c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;  
  174. _NODELAY_DISABLED;  
  175. #if (NGX_SOLARIS)  
  176. _INET及AF_INET6 */   
  177.             c->sendfile =         }  
  178. #endif  
  179.         rev = c->閱讀;  
  180.         wev =       我們->準備= 1;    
  181.        (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {              /* rtsig、 aio、 iocp */
  182.   
  183.             rev->就緒= 1;          }  
  184.   
  185.          if (ev->deferred_accept) {  
  186.             轉速UE)
  187.   
  188.             rev->可用 = 1;  
  189. #endif
  190.   
  191.         }
  192.   
  193.         rev->log = log;  
  194.   
  195.         /* 
  196.  () 
  197.          *                * 
  198.          * TODO: MP: - 分配在共享記憶體中 * TODO: MP: - 分配在共享記憶體中 * TODO: MP: - 分配在共享記憶體中 
  199.          *           - ngx_atomic_fetch_add()       或透過臨界區域或輕斥體保護 
  200.          */       c->number = ngx_atomic_fetch_add (ngx_connection_counter, 1);  
  201.           
  202.    _flags & NGX_USE_EPOLL_EVENT) == 0) {  
  203.         
  204.                 ngx_close_accepted_connection  ;  
  205.             }    
  206.            
  207.      
  208.     ->handler = NULL;            
  209.          這裡聽 handler 非常重要,它完成了新連結的最後一個初始化工作, 
  210.         同時接受新的連結到epoll;掛在這個handler上的函數,
  211.  
  212.         就是ngx_http_init_connection */  
  213.         ls->handler(c );  
  214.   
  215.         if
  216.  (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {  
  217.             ev->ava不可以——;  
  218.         }  
  219.       } 
  220. while
  221. (ev->可用);  
  222. }  
  223. accpt事件的handler方法就這樣了。之後就是每個連接的讀寫器事件handler方法,這部分會直接將我們引入http模組,我們不著急,還要學習下nginx經典模組epoll。

    以上就介紹了nginx 原始碼學習筆記(二十一)—— event 模組二 ——事件驅動核心ngx_process_events_and_timers,包括了隊列方面的內容,希望對PHP教程有興趣的朋友有所幫助。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn