Reprinted statement: This article can be reproduced at will, but the original address must be specified. Thank you!
The title of this article has made me struggle for a long time. I don't know whether the connections array is suitable or the connections linked list is more suitable. nginx has injected more or less the characteristics of the two, whether it's an array or a linked list, you just have to figure out what this connections is. Each worker process in nginx uses the same connections array to maintain each connection. When a new connection is established, nginx needs to extract a slot from the array to store the connection. On the contrary, when a connection is disconnected, you also need to return the corresponding slot to the connections array. This article describes how the connections array is constructed to make nginx easy and fast to get/release a slot. I have pieced together the following code from the ngx_event_process_init () function:
/* Allocate an array */<br/> cycle-> connections = <br/> ngx_alloc (sizeof (ngx_connection_t) * cycle-> connection_n, cycle-> log ); <br/> If (cycle-> connections = NULL) {<br/> return ngx_error; <br/>}< br/> C = Cycle-> connections; <br/> I = Cycle-> connection_n; <br/> next = NULL; <br/>/* string all slots in the array with pointers, form a linked list */<br/> do {<br/> I --; <br/> C [I]. data = next; <br/> ................. <Br/> next = & C [I]; <br/>}while (I ); <br/>/* free_connections points to an available slot */<br/> cycle-> free_connections = next; <br/>/* Number of available slots of free_connection_n */<br/> cycle-> free_connection_n = Cycle-> connection_n;
After the above Code, the data structure is shown in:
Now nginx has constructed an empty connections array for us. We need to establish a new connection, so call the ngx_get_connection () function () obtain an available slot from the connections array to maintain the connection. First, let's take a look at the simplified implementation of the ngx_get_connection () function:
Ngx_connection_t * <br/> ngx_get_connection (ngx_socket_t S, ngx_log_t * log) <br/>{< br/> ngx_uint_t instance; <br/> ngx_event_t * Rev, * WEV; <br/> ngx_connection_t * C; <br/> ............ </P> <p>/* obtain an available slot from free_connecionts */<br/> C = ngx_cycle-> free_connections; <br/> If (C = NULL) {<br/> return NULL; <br/>}< br/>/* move the free_connections pointer to the next available slot of the retrieved C */<br/> ngx_cycle-> free_connections = C-> data; <br/> ngx_cycle-> free_connection_n --; <br/> ........ /* Omitted many operations on C */<br/> return C; <br/>}
Obtain a slot from the newly created connections array, as follows:
In the above state, we get another slot, then we get the following result:
At this point, we basically understand how to obtain a slot from the connections array. Next, let's look at how to release a slot. The ngx_get_connection () function corresponds to the ngx_free_connection () function. The simplified implementation is as follows:
Void <br/> ngx_free_connection (ngx_connection_t * C) <br/> {<br/>/* slot C pointer available slot linked list header */<br/> C-> DATA = ngx_cycle-> free_connections; <br/>/* Move free_connections to C */<br/> ngx_cycle-> free_connections = C; <br/> ngx_cycle-> free_connection_n ++; <br/> ........ <Br/>}< br/>
The effect of releasing the first acquired slot is as follows:
After the second acquired slot is released, it becomes the following effect:
Although the entire connections array is not used at the end, it is still different from the first creation. But the most important thing is that all slots that can be used are still on a linked list, but the Slot Sequence is different. This article only provides a very simple case for getting and releasing slots. You can obtain and release slots in a whimsical order to construct a seemingly complex linked list, but the essence is always the same.
A good data structure is not only efficient, but also easy to use. nginx has done this in terms of connection maintenance.