This blog (http://blog.csdn.net/livelylittlefish) posted the author (a wave) related research, learning content of the Notes, welcome to the majority of friends correct!
Content
1. Linked List Structure
1.2 logical structure of ngx_list_t
2.1 create a linked list
3. An example
3.2 how to compile
4. Summary
0. Order
This article continues to introduce the nginx container-linked list.
Linked List Implementation file:./src/CORE/ngx_list.h/. C .. Represents the nginx-1.0.4 code directory, this article is/usr/src/nginx-1.0.4.
1. Linked List Structure
1.1 ngx_list_t Structure
The nginx linked list (header) structure is ngx_list_t, and the linked list node structure is ngx_list_part_t, which is defined as follows.
Typedef struct ngx_list_part_s ngx_list_part_t; struct ngx_list_part_s {// void * ELTs; // point to the actual data area of the node (the data area can store nalloc elements of size) ngx_uint_t nelts; // The number of actually stored elements ngx_list_part_t * next; // point to the next node}; typedef struct {// ngx_list_part_t * last; // point to the last node (Part) ngx_list_part_t part of the linked list; // The first node (Part) size_t size contained in the linked list header; // the size of each element ngx_uint_t nalloc; // the number of spaces contained in the linked list, that is, the number of actually allocated small spaces ngx_pool_t * pool; // The Node space of the linked list is allocated in this memory pool} ngx_list_t;
Sizeof (ngx_list_t) = 28, sizeof (ngx_list_part_t) = 12.
It can be seen that the nginx linked list should also be allocated from the memory pool. For each node (list part), nalloc will be allocated a small space of size, and the actual allocated size is (nalloc * size ). For more information, see the following analysis.
1.2 logical structure of ngx_list_t
The ngx_list_t structure references the ngx_pool_t structure, so this article refer to the nginx-1.0.4 source code analysis-Memory Pool Structure ngx_pool_t and memory management to draw a logical diagram of the relevant structure, as follows. Note: This document uses UML to draw the diagram.
2. Linked List Operation
There are three linked list operations, as shown below.
// Create the linked list ngx_list_t * ngx_list_create (memory * Pool, memory N, size_t size); // initialize the static ngx_inline ngx_int_t ngx_list_init (ngx_list_t * List, memory * Pool, ngx_uint_tn, size_t size); // Add the element void * ngx_list_push (ngx_list_t * l)
Their implementation is very simple. This article only analyzes how to create a linked list and add elements.
2.1 create a linked list
The following describes how to create a linked list. First, assign the linked list header (28B) and then assign the header node (that is, the part contained in the linked list header) to the data area, both distributions are performed in the input Memory Pool (the pool points to the memory pool. Then, initialize the linked list header and return the starting position of the linked list header.
Ngx_list_t * ngx_list_create (ngx_pool_t * Pool, ngx_uint_t N, size_t size) {ngx_list_t * List; List = ngx_palloc (pool, sizeof (ngx_list_t )); // allocate the chain table header from the memory pool if (list = NULL) {return NULL;} List-> part. ELTs = ngx_palloc (pool, N * size); // then, the area of N * size is allocated as the data area of the linked list if (list-> part. ELTs = NULL) {return NULL;} List-> part. nelts = 0; // initialize list-> part. next = NULL; List-> last = & list-> part; List-> size = size; List-> nalloc = N; List-> pool = pool; return list; // return the start position of the linked list header}
The physical structure of the memory pool after the linked list is created is as follows.
2.2 add element
The add element operation is implemented as follows. Similar to the nginx array implementation, the actual addition operation is not completed in this function. The ngx_list_push function returns the position where elements (one or more elements) can be placed in the data area of the linked list. The add operation is performed after obtaining the Add position, as shown in the following example.
Void * ngx_list_push (ngx_list_t * l) {void * ELT; ngx_list_part_t * last; last = L-> last; If (last-> nelts = L-> nalloc) {// full/* the last part is full, allocate anew list part */last = ngx_palloc (L-> pool, sizeof (ngx_list_part_t )); // assign a node (list part) if (last = NULL) {return NULL;} Last-> ELTs = ngx_palloc (L-> pool, l-> nalloc * l-> size); // If (last-> ELTs = NULL) {return NULL ;} last-> nelts = 0; last-> next = NULL; L-> last-> next = last; // Insert the allocated list part to the linked list l-> last = last; // Modify the last pointer of the List header} ELT = (char *) Last-> ELTs + L-> size * Last-> nelts; // calculate the location of the next data in the Linked List data area last-> nelts ++; // Add 1 return ELT to the number of actually stored data; // return this location}
It can be seen that adding elements to the linked list is actually allocating the linked list node (Part) and the actual data zone of the node from the memory pool, and modifying the linked list node (Part) information.
NOTE 1: In contrast to arrays, when the array data area is full, the space in the data area needs to be expanded, and the linked list needs to allocate nodes and their data areas each time.
NOTE 2: one or more elements can be placed in the data area of each node (part) of the linked list. The elements here can be an integer or a structure.
Is a logical structure of a linked list with three nodes.
There are too many lines in the figure and it is easy to get dizzy. The figure below may be better.
3. An example
The best way to understand and master open-source software is to write some test code by yourself, or rewrite the software itself and debug it to further understand the principles and design methods of open-source software. This section provides a simple example of creating a memory pool and allocating a linked list from it. In this example, each node (part) of the linked list can store five elements, each of which is 4 bytes in size. After creating the linked list, add 15 integer elements to the linked list.
Code 3.1
/** * ngx_list_t test, to test ngx_list_create, ngx_list_push */#include <stdio.h>#include "ngx_config.h"#include "ngx_conf_file.h"#include "nginx.h"#include "ngx_core.h"#include "ngx_string.h"#include "ngx_palloc.h"#include "ngx_list.h"volatile ngx_cycle_t *ngx_cycle;void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...){}void dump_pool(ngx_pool_t* pool){ while (pool) { printf("pool = 0x%x\n", pool); printf(" .d\n"); printf(" .last = 0x%x\n", pool->d.last); printf(" .end = 0x%x\n", pool->d.end); printf(" .next = 0x%x\n", pool->d.next); printf(" .failed = %d\n", pool->d.failed); printf(" .max = %d\n", pool->max); printf(" .current = 0x%x\n", pool->current); printf(" .chain = 0x%x\n", pool->chain); printf(" .large = 0x%x\n", pool->large); printf(" .cleanup = 0x%x\n", pool->cleanup); printf(" .log = 0x%x\n", pool->log); printf("available pool memory = %d\n\n", pool->d.end - pool->d.last); pool = pool->d.next; }}void dump_list_part(ngx_list_t* list, ngx_list_part_t* part){ int *ptr = (int*)(part->elts); int loop = 0; printf(" .part = 0x%x\n", &(list->part)); printf(" .elts = 0x%x ", part->elts); printf("("); for (; loop < list->nalloc - 1; loop++) { printf("0x%x, ", ptr[loop]); } printf("0x%x)\n", ptr[loop]); printf(" .nelts = %d\n", part->nelts); printf(" .next = 0x%x", part->next); if (part->next) printf(" -->\n"); printf(" \n");}void dump_list(ngx_list_t* list){ if (list == NULL) return; printf("list = 0x%x\n", list); printf(" .last = 0x%x\n", list->last); printf(" .part = 0x%x\n", &(list->part)); printf(" .size = %d\n", list->size); printf(" .nalloc = %d\n", list->nalloc); printf(" .pool = 0x%x\n\n", list->pool); printf("elements:\n"); ngx_list_part_t *part = &(list->part); while (part) { dump_list_part(list, part); part = part->next; } printf("\n");}int main(){ ngx_pool_t *pool; int i; printf("--------------------------------\n"); printf("create a new pool:\n"); printf("--------------------------------\n"); pool = ngx_create_pool(1024, NULL); dump_pool(pool); printf("--------------------------------\n"); printf("alloc an list from the pool:\n"); printf("--------------------------------\n"); ngx_list_t *list = ngx_list_create(pool, 5, sizeof(int)); dump_pool(pool); for (i = 0; i < 15; i++) { int *ptr = ngx_list_push(list); *ptr = i + 1; } printf("--------------------------------\n"); printf("the list information:\n"); printf("--------------------------------\n"); dump_list(list); printf("--------------------------------\n"); printf("the pool at the end:\n"); printf("--------------------------------\n"); dump_pool(pool); ngx_destroy_pool(pool); return 0;}
3.2 how to compile
See the nginx-1.0.4 source code analysis-Memory Pool Structure ngx_pool_t and Memory Management Article. The MAKEFILE file written in this article is as follows.
CXX = gccCXXFLAGS +=-g -Wall -Wextra NGX_ROOT =/usr/src/nginx-1.0.4 TARGETS =ngx_list_t_testTARGETS_C_FILE= $(TARGETS).c CLEANUP = rm-f $(TARGETS) *.o all:$(TARGETS) clean:$(CLEANUP) CORE_INCS =-I. \-I$(NGX_ROOT)/src/core \-I$(NGX_ROOT)/src/event \-I$(NGX_ROOT)/src/event/modules \-I$(NGX_ROOT)/src/os/unix \-I$(NGX_ROOT)/objs \ NGX_PALLOC =$(NGX_ROOT)/objs/src/core/ngx_palloc.oNGX_STRING =$(NGX_ROOT)/objs/src/core/ngx_string.oNGX_ALLOC =$(NGX_ROOT)/objs/src/os/unix/ngx_alloc.oNGX_LIST =$(NGX_ROOT)/objs/src/core/ngx_list.o $(TARGETS):$(TARGETS_C_FILE)$(CXX) $(CXXFLAGS) $(CORE_INCS) $(NGX_PALLOC) $(NGX_STRING)$(NGX_ALLOC) $(NGX_LIST) $^ -o $@
3.3 running results
# ./ngx_list_t_test-------------------------------- create a new pool:-------------------------------- pool = 0x9208020 .d .last = 0x9208048 .end = 0x9208420 .next = 0x0 .failed = 0 .max = 984 .current = 0x9208020 .chain = 0x0 .large = 0x0 .cleanup = 0x0 .log = 0x0 available pool memory = 984-------------------------------- alloc an list from the pool:-------------------------------- pool = 0x9208020 .d .last = 0x9208078 .end = 0x9208420 .next = 0x0 .failed = 0 .max = 984 .current = 0x9208020 .chain = 0x0 .large = 0x0 .cleanup = 0x0 .log = 0x0 available pool memory = 936-------------------------------- the list information:-------------------------------- list = 0x9208048 .last = 0x9208098 .part = 0x920804c .size = 4 .nalloc = 5 .pool = 0x9208020elements: .part = 0x920804c .elts = 0x9208064 (0x1, 0x2, 0x3, 0x4, 0x5) .nelts = 5 .next = 0x9208078 --> .part = 0x920804c .elts = 0x9208084 (0x6, 0x7, 0x8, 0x9, 0xa) .nelts = 5 .next = 0x9208098 --> .part = 0x920804c .elts = 0x92080a4 (0xb, 0xc, 0xd, 0xe, 0xf) .nelts = 5 .next = 0x0 -------------------------------- the pool at the end:-------------------------------- pool = 0x9208020 .d .last = 0x92080b8 .end = 0x9208420 .next = 0x0 .failed = 0 .max = 984 .current = 0x9208020 .chain = 0x0 .large = 0x0 .cleanup = 0x0 .log = 0x0 available pool memory = 872
In this example, for the physical structure of the memory pool and array (memory), refer to the figure in section 2.3.
4. Summary
In this paper, the nginx-1.0.4 container-linked list structure is more comprehensive analysis, including linked list related data structure, linked list creation and add elements to the linked list. Finally, we use a simple example to show you how to create and add elements to the nginx linked list, and how to compile and test code.
Please pay attention to the subsequent analysis. Thank you!
Reference
Nginx code Research Plan (rainx1982)
Nginx-1.0.4 source code analysis-Memory Pool Structure ngx_pool_t and memory management (APO)