: 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?
- Src/event/ngx_event.c
-
- Void
- Ngx_process_events_and_timers (ngx_cycle_t * cycle)
- {
- Ngx_uint_t flags;
- Ngx_msec_t timer, delta;
-
- If (ngx_timer_resolution ){
- Timer = NGX_TIMER_INFINITE;
- Flags = 0;
-
- } Else {
- Timer = ngx_event_find_timer ();
- Flags = NGX_UPDATE_TIME;
- }
-
- /*
- The ngx_use_accept_mutex variable indicates whether to use the accept mutex.
- It is used by default and can be disabled through the accept_mutex off Command;
- The role of accept mutex is to avoid group alarms and achieve load balancing.
- */
- If (ngx_use_accept_mutex ){
-
- /*
- The ngx_accept_disabled variable is calculated in the ngx_event_accept function.
- If ngx_accept_disabled is greater than 0, this indicates that the process has received too many connections,
- Therefore, I gave up a chance to compete for accept mutex and reduced myself by one.
- Then, continue to process the events on the existing connection.
- Nginx uses this to achieve load balancing that inherits the basic connection.
- */
- If (ngx_accept_disabled> 0 ){
- Ngx_accept_disabled --;
-
- } Else {
- /*
- Try to lock accept mutex. only the process that successfully acquires the lock will put the listen socket in epoll.
- Therefore, this ensures that only one process has a listening set interface, so when all processes are blocked in epoll_wait,
- It is not surprising.
- */
- If (ngx_trylock_accept_mutex (cycle) = NGX_ERROR ){
- Return;
- }
-
- If (ngx_accept_mutex_held ){
- /*
- If the process gets the lock, an NGX_POST_EVENTS flag is added.
- This flag is used to put all generated events into oneQueueAfter being released, you are processing the event slowly.
- 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,
- As a result, other processes cannot obtain the lock, which reduces the accept efficiency.
- */
- Flags | = NGX_POST_EVENTS;
-
- } Else {
- /*
- No process is obtained. of course, the NGX_POST_EVENTS flag is not required.
- However, you need to set the delay time to compete for the lock.
- */
- If (timer = NGX_TIMER_INFINITE
- | Timer> ngx_accept_mutex_delay)
- {
- Timer = ngx_accept_mutex_delay;
- }
- }
- }
- }
-
- Delta = ngx_current_msec;
-
- /* Next, epoll starts wait events,
- The specific implementation of ngx_process_events corresponds to the ngx_epoll_process_events function in the epoll module.
- I will explain it in detail later.
- */
- (Void) ngx_process_events (cycle, timer, flags );
- // Count the time consumed by this wait event
- Delta = ngx_current_msec-delta;
-
- Ngx_log_debug1 (NGX_LOG_DEBUG_EVENT, cycle-> log, 0,
- "Timer delta: % M", delta );
-
- /*
- Ngx_posted_accept_events is an event.QueueTemporarily store the accept event from the listening set interface wait to epoll.
- After the NGX_POST_EVENTS mark is used, all the accept events will be saved to thisQueue
- */
- If (ngx_posted_accept_events ){
- Ngx_event_process_posted (cycle, & ngx_posted_accept_events );
- }
- // After all the accept events are processed, if the lock is held, it will be released.
- If (ngx_accept_mutex_held ){
- Ngx_shmtx_unlock (& ngx_accept_mutex );
- }
-
- /*
- Delta is the time consumed in previous statistics. if the time consumed in milliseconds exists, it checks all the time timer,
- 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.
- */
- If (delta ){
- Ngx_event_expire_timers ();
- }
-
- Ngx_log_debug1 (NGX_LOG_DEBUG_EVENT, cycle-> log, 0,
- "Posted events % p", ngx_posted_events );
-
- /*
- Process common events (read/write events obtained on the connection ),
- Because each event has its own handler method,
- */
- If (ngx_posted_events ){
- If (ngx_threaded ){
- Ngx_wakeup_worker_thread (cycle );
-
- } Else {
- Ngx_event_process_posted (cycle, & ngx_posted_events );
- }
- }
- }
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?
- Src/event/ngx_event_accept.c
-
- Void
- Ngx_event_accept (ngx_event_t * ev)
- {
- Socklen_t socklen;
- Ngx_err_t err;
- Ngx_log_t * log;
- Ngx_socket_t s;
- Ngx_event_t * rev, * wev;
- Ngx_listening_t * ls;
- Ngx_connection_t * c, * lc;
- Ngx_event_conf_t * ecf;
- U_char sa [NGX_SOCKADDRLEN];
-
- // Omit part of the code
-
- Lc = ev-> data;
- Ls = lc-> listening;
- Ev-> ready = 0;
-
- Ngx_log_debug2 (NGX_LOG_DEBUG_EVENT, ev-> log, 0,
- "Accept on % V, ready: % d", & ls-> addr_text, ev-> available );
-
- Do {
- Socklen = NGX_SOCKADDRLEN;
- // Accept a new connection
- S = accept (lc-> fd, (struct sockaddr *) sa, & socklen );
- // Omit part of the code
-
- /*
- After the accept is connected to a new connection, it recalculates the value of ngx_accept_disabled,
- It is mainly used for load balancing and has been mentioned before.
-
- Here, we can see that his method is only
- "1/8 of total connections-remaining connections"
- Total connections are the maximum number of connections set by each process. this number can be specified in the configuration file.
-
- 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.
-
- */
-
- Ngx_accept_disabled = ngx_cycle-> connection_n/8
- -Ngx_cycle-> free_connection_n;
-
- // Obtain a connection
- C = ngx_get_connection (s, ev-> log );
-
- // Create a memory pool for the new link
- // The pool is released only when the connection is closed.
-
- C-> pool = ngx_create_pool (ls-> pool_size, ev-> log );
- If (c-> pool = NULL ){
- Ngx_close_accepted_connection (c );
- Return;
- }
-
- C-> sockaddr = ngx_palloc (c-> pool, socklen );
- If (c-> sockaddr = NULL ){
- Ngx_close_accepted_connection (c );
- Return;
- }
-
- Ngx_memcpy (c-> sockaddr, sa, socklen );
-
- Log = ngx_palloc (c-> pool, sizeof (ngx_log_t ));
- If (log = NULL ){
- Ngx_close_accepted_connection (c );
- Return;
- }
-
- /* Set a blocking mode for aio and non-blocking mode for others */
-
- If (ngx_inherited_nonblocking ){
- If (ngx_event_flags & NGX_USE_AIO_EVENT ){
- If (ngx_blocking (s) =-1 ){
- Ngx_log_error (NGX_LOG_ALERT, ev-> log, ngx_socket_errno,
- Ngx_blocking_n "failed ");
- Ngx_close_accepted_connection (c );
- Return;
- }
- }
-
- } Else {
- // We use the epoll model. Here we set the connection to nonblocking.
- If (! (Ngx_event_flags & (NGX_USE_AIO_EVENT | NGX_USE_RTSIG_EVENT ))){
- If (ngx_nonblocking (s) =-1 ){
- Ngx_log_error (NGX_LOG_ALERT, ev-> log, ngx_socket_errno,
- Ngx_nonblocking_n "failed ");
- Ngx_close_accepted_connection (c );
- Return;
- }
- }
- }
-
- * Log = ls-> log;
- // Initialize a new connection
- C-> recv = ngx_recv;
- C-> send = ngx_send;
- C-> recv_chain = ngx_recv_chain;
- C-> send_chain = ngx_send_chain;
-
- C-> log = log;
- C-> pool-> log = log;
-
- C-> socklen = socklen;
- C-> listening = ls;
- C-> local_sockaddr = ls-> sockaddr;
-
- C-> unexpected_eof = 1;
-
- # If (NGX_HAVE_UNIX_DOMAIN)
- If (c-> sockaddr-> sa_family = AF_UNIX ){
- C-> tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
- C-> tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
- # If (NGX_SOLARIS)
- /* Solaris's sendfilev () supports AF_NCA, AF_INET, and AF_INET6 */
- C-> sendfile = 0;
- # Endif
- }
- # Endif
-
- Rev = c-> read;
- Wev = c-> write;
-
- Wev-> ready = 1;
-
- If (ngx_event_flags & (NGX_USE_AIO_EVENT | NGX_USE_RTSIG_EVENT )){
- /* Rtsig, aio, iocp */
- Rev-> ready = 1;
- }
-
- If (ev-> deferred_accept ){
- Rev-> ready = 1;
- # If (NGX_HAVE_KQUEUE)
- Rev-> available = 1;
- # Endif
- }
-
- Rev-> log = log;
- Wev-> log = log;
-
- /*
- * TODO: MT:-ngx_atomic_fetch_add ()
- * Or protection by critical section or light mutex
- *
- * TODO: MP:-allocated in a shared memory
- *-Ngx_atomic_fetch_add ()
- * Or protection by critical section or light mutex
- */
-
- C-> number = ngx_atomic_fetch_add (ngx_connection_counter, 1 );
-
- If (ngx_add_conn & (ngx_event_flags & NGX_USE_EPOLL_EVENT) = 0 ){
- If (ngx_add_conn (c) = NGX_ERROR ){
- Ngx_close_accepted_connection (c );
- Return;
- }
- }
-
- Log-> data = NULL;
- Log-> handler = NULL;
-
- /*
- Here, listen handler is very important. it will complete the final initialization of the new connection,
- At the same time, put the new connection from the accept into epoll; the function that hangs on the handler,
- Ngx_http_init_connection is described in detail in the subsequent http module.
- */
- Ls-> handler (c );
-
- If (ngx_event_flags & NGX_USE_KQUEUE_EVENT ){
- Ev-> available --;
- }
-
- } While (ev-> available );
- }
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.