Nginx source code learning notes (21) -- event Module 2 -- event-driven core ngx_process_events_and_timers

Source: Internet
Author: User
: This article mainly introduces the nginx source code learning notes (21) -- event Module 2 -- the event-driven core ngx_process_events_and_timers. if you are interested in the PHP Tutorial, refer to it. First, let's continue to recall that there was a non-involved ngx_process_events_and_timers in the previous sub-thread execution operation. today we will study this function.

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

Let's take a look at the part in section 19th:


Today we will mainly explain the event-driven functions, in the red part of the figure:

[Cpp] view plaincopyprint?

  1. Src/event/ngx_event.c
  2. Void
  3. Ngx_process_events_and_timers (ngx_cycle_t * cycle)
  4. {
  5. Ngx_uint_t flags;
  6. Ngx_msec_t timer, delta;
  7. If (ngx_timer_resolution ){
  8. Timer = NGX_TIMER_INFINITE;
  9. Flags = 0;
  10. } Else {
  11. Timer = ngx_event_find_timer ();
  12. Flags = NGX_UPDATE_TIME;
  13. }
  14. /*
  15. The ngx_use_accept_mutex variable indicates whether to use the accept mutex.
  16. It is used by default and can be disabled through the accept_mutex off Command;
  17. The role of accept mutex is to avoid group alarms and achieve load balancing.
  18. */
  19. If (ngx_use_accept_mutex ){
  20. /*
  21. The ngx_accept_disabled variable is calculated in the ngx_event_accept function.
  22. If ngx_accept_disabled is greater than 0, this indicates that the process has received too many connections,
  23. Therefore, I gave up a chance to compete for accept mutex and reduced myself by one.
  24. Then, continue to process the events on the existing connection.
  25. Nginx uses this to achieve load balancing that inherits the basic connection.
  26. */
  27. If (ngx_accept_disabled> 0 ){
  28. Ngx_accept_disabled --;
  29. } Else {
  30. /*
  31. Try to lock accept mutex. only the process that successfully acquires the lock will put the listen socket in epoll.
  32. Therefore, this ensures that only one process has a listening set interface, so when all processes are blocked in epoll_wait,
  33. It is not surprising.
  34. */
  35. If (ngx_trylock_accept_mutex (cycle) = NGX_ERROR ){
  36. Return;
  37. }
  38. If (ngx_accept_mutex_held ){
  39. /*
  40. If the process gets the lock, an NGX_POST_EVENTS flag is added.
  41. This flag is used to put all generated events into oneQueueAfter being released, you are processing the event slowly.
  42. Because the processing time may be very time-consuming. if the lock is not applied before processing, the process occupies the lock for a long time,
  43. As a result, other processes cannot obtain the lock, which reduces the accept efficiency.
  44. */
  45. Flags | = NGX_POST_EVENTS;
  46. } Else {
  47. /*
  48. No process is obtained. of course, the NGX_POST_EVENTS flag is not required.
  49. However, you need to set the delay time to compete for the lock.
  50. */
  51. If (timer = NGX_TIMER_INFINITE
  52. | Timer> ngx_accept_mutex_delay)
  53. {
  54. Timer = ngx_accept_mutex_delay;
  55. }
  56. }
  57. }
  58. }
  59. Delta = ngx_current_msec;
  60. /* Next, epoll starts wait events,
  61. The specific implementation of ngx_process_events corresponds to the ngx_epoll_process_events function in the epoll module.
  62. I will explain it in detail later.
  63. */
  64. (Void) ngx_process_events (cycle, timer, flags );
  65. // Count the time consumed by this wait event
  66. Delta = ngx_current_msec-delta;
  67. Ngx_log_debug1 (NGX_LOG_DEBUG_EVENT, cycle-> log, 0,
  68. "Timer delta: % M", delta );
  69. /*
  70. Ngx_posted_accept_events is an event.QueueTemporarily store the accept event from the listening set interface wait to epoll.
  71. After the NGX_POST_EVENTS mark is used, all the accept events will be saved to thisQueue
  72. */
  73. If (ngx_posted_accept_events ){
  74. Ngx_event_process_posted (cycle, & ngx_posted_accept_events );
  75. }
  76. // After all the accept events are processed, if the lock is held, it will be released.
  77. If (ngx_accept_mutex_held ){
  78. Ngx_shmtx_unlock (& ngx_accept_mutex );
  79. }
  80. /*
  81. Delta is the time consumed in previous statistics. if the time consumed in milliseconds exists, it checks all the time timer,
  82. If timeout is used, the expired timer is deleted from the time rbtree, and the handler function of the corresponding event is called for processing.
  83. */
  84. If (delta ){
  85. Ngx_event_expire_timers ();
  86. }
  87. Ngx_log_debug1 (NGX_LOG_DEBUG_EVENT, cycle-> log, 0,
  88. "Posted events % p", ngx_posted_events );
  89. /*
  90. Process common events (read/write events obtained on the connection ),
  91. Because each event has its own handler method,
  92. */
  93. If (ngx_posted_events ){
  94. If (ngx_threaded ){
  95. Ngx_wakeup_worker_thread (cycle );
  96. } Else {
  97. Ngx_event_process_posted (cycle, & ngx_posted_events );
  98. }
  99. }
  100. }


As mentioned before, the accept event is actually a new event on the listening set interface. The following describes the handler method of the accept time:

Ngx_event_accept:

[Cpp] view plaincopyprint?

  1. Src/event/ngx_event_accept.c
  2. Void
  3. Ngx_event_accept (ngx_event_t * ev)
  4. {
  5. Socklen_t socklen;
  6. Ngx_err_t err;
  7. Ngx_log_t * log;
  8. Ngx_socket_t s;
  9. Ngx_event_t * rev, * wev;
  10. Ngx_listening_t * ls;
  11. Ngx_connection_t * c, * lc;
  12. Ngx_event_conf_t * ecf;
  13. U_char sa [NGX_SOCKADDRLEN];
  14. // Omit part of the code
  15. Lc = ev-> data;
  16. Ls = lc-> listening;
  17. Ev-> ready = 0;
  18. Ngx_log_debug2 (NGX_LOG_DEBUG_EVENT, ev-> log, 0,
  19. "Accept on % V, ready: % d", & ls-> addr_text, ev-> available );
  20. Do {
  21. Socklen = NGX_SOCKADDRLEN;
  22. // Accept a new connection
  23. S = accept (lc-> fd, (struct sockaddr *) sa, & socklen );
  24. // Omit part of the code
  25. /*
  26. After the accept is connected to a new connection, it recalculates the value of ngx_accept_disabled,
  27. It is mainly used for load balancing and has been mentioned before.
  28. Here, we can see that his method is only
  29. "1/8 of total connections-remaining connections"
  30. Total connections are the maximum number of connections set by each process. this number can be specified in the configuration file.
  31. Therefore, after each process reaches 7/8 of the total number of connections, ngx_accept_disabled is greater than zero, and the connection is overloaded.
  32. */
  33. Ngx_accept_disabled = ngx_cycle-> connection_n/8
  34. -Ngx_cycle-> free_connection_n;
  35. // Obtain a connection
  36. C = ngx_get_connection (s, ev-> log );
  37. // Create a memory pool for the new link
  38. // The pool is released only when the connection is closed.
  39. C-> pool = ngx_create_pool (ls-> pool_size, ev-> log );
  40. If (c-> pool = NULL ){
  41. Ngx_close_accepted_connection (c );
  42. Return;
  43. }
  44. C-> sockaddr = ngx_palloc (c-> pool, socklen );
  45. If (c-> sockaddr = NULL ){
  46. Ngx_close_accepted_connection (c );
  47. Return;
  48. }
  49. Ngx_memcpy (c-> sockaddr, sa, socklen );
  50. Log = ngx_palloc (c-> pool, sizeof (ngx_log_t ));
  51. If (log = NULL ){
  52. Ngx_close_accepted_connection (c );
  53. Return;
  54. }
  55. /* Set a blocking mode for aio and non-blocking mode for others */
  56. If (ngx_inherited_nonblocking ){
  57. If (ngx_event_flags & NGX_USE_AIO_EVENT ){
  58. If (ngx_blocking (s) =-1 ){
  59. Ngx_log_error (NGX_LOG_ALERT, ev-> log, ngx_socket_errno,
  60. Ngx_blocking_n "failed ");
  61. Ngx_close_accepted_connection (c );
  62. Return;
  63. }
  64. }
  65. } Else {
  66. // We use the epoll model. Here we set the connection to nonblocking.
  67. If (! (Ngx_event_flags & (NGX_USE_AIO_EVENT | NGX_USE_RTSIG_EVENT ))){
  68. If (ngx_nonblocking (s) =-1 ){
  69. Ngx_log_error (NGX_LOG_ALERT, ev-> log, ngx_socket_errno,
  70. Ngx_nonblocking_n "failed ");
  71. Ngx_close_accepted_connection (c );
  72. Return;
  73. }
  74. }
  75. }
  76. * Log = ls-> log;
  77. // Initialize a new connection
  78. C-> recv = ngx_recv;
  79. C-> send = ngx_send;
  80. C-> recv_chain = ngx_recv_chain;
  81. C-> send_chain = ngx_send_chain;
  82. C-> log = log;
  83. C-> pool-> log = log;
  84. C-> socklen = socklen;
  85. C-> listening = ls;
  86. C-> local_sockaddr = ls-> sockaddr;
  87. C-> unexpected_eof = 1;
  88. # If (NGX_HAVE_UNIX_DOMAIN)
  89. If (c-> sockaddr-> sa_family = AF_UNIX ){
  90. C-> tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
  91. C-> tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
  92. # If (NGX_SOLARIS)
  93. /* Solaris's sendfilev () supports AF_NCA, AF_INET, and AF_INET6 */
  94. C-> sendfile = 0;
  95. # Endif
  96. }
  97. # Endif
  98. Rev = c-> read;
  99. Wev = c-> write;
  100. Wev-> ready = 1;
  101. If (ngx_event_flags & (NGX_USE_AIO_EVENT | NGX_USE_RTSIG_EVENT )){
  102. /* Rtsig, aio, iocp */
  103. Rev-> ready = 1;
  104. }
  105. If (ev-> deferred_accept ){
  106. Rev-> ready = 1;
  107. # If (NGX_HAVE_KQUEUE)
  108. Rev-> available = 1;
  109. # Endif
  110. }
  111. Rev-> log = log;
  112. Wev-> log = log;
  113. /*
  114. * TODO: MT:-ngx_atomic_fetch_add ()
  115. * Or protection by critical section or light mutex
  116. *
  117. * TODO: MP:-allocated in a shared memory
  118. *-Ngx_atomic_fetch_add ()
  119. * Or protection by critical section or light mutex
  120. */
  121. C-> number = ngx_atomic_fetch_add (ngx_connection_counter, 1 );
  122. If (ngx_add_conn & (ngx_event_flags & NGX_USE_EPOLL_EVENT) = 0 ){
  123. If (ngx_add_conn (c) = NGX_ERROR ){
  124. Ngx_close_accepted_connection (c );
  125. Return;
  126. }
  127. }
  128. Log-> data = NULL;
  129. Log-> handler = NULL;
  130. /*
  131. Here, listen handler is very important. it will complete the final initialization of the new connection,
  132. At the same time, put the new connection from the accept into epoll; the function that hangs on the handler,
  133. Ngx_http_init_connection is described in detail in the subsequent http module.
  134. */
  135. Ls-> handler (c );
  136. If (ngx_event_flags & NGX_USE_KQUEUE_EVENT ){
  137. Ev-> available --;
  138. }
  139. } While (ev-> available );
  140. }


The handler method of the accpt event is the same. Then there is the handler method for each connection read/write event. This part will directly introduce us to the http Module. we are not in a hurry, but also need to learn epoll of the nginx classic module.

The above introduces the nginx source code learning notes (21) -- event Module 2 -- the event-driven core ngx_process_events_and_timers, including the Queue Content, hope to be helpful to friends who are interested in PHP tutorials.

Related Article

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.