Home  >  Article  >  Backend Development  >  [nginx source code analysis]ngx memory pool implementation

[nginx source code analysis]ngx memory pool implementation

WBOY
WBOYOriginal
2016-08-08 09:24:461086browse

Memory pool function:

ngx_create_pool
ngx_destroy_pool
ngx_reset_pool
ngx_palloc
ngx_pnalloc
ngx_palloc_block
ngx_palloc_large
ngx_pool_cleanup_add

Memory pool creation

ngx_pool_t *
  ngx_create_pool(size_t size, ngx_log_t *log)
  {
      ngx_pool_t  *p;
  
      p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);//按照16字节对齐分配一块size大小内存
      if (p == NULL) {
          return NULL;
      }                                                                                                                                                              
  
      p->d.last = (u_char *) p + sizeof(ngx_pool_t);  //last指向数据部分开始(跳过header ngx_pool_t)结构
      p->d.end = (u_char *) p + size;                 //end指向末尾结构
      p->d.next = NULL;                               //next是对小块内存链表管理指针
      p->d.failed = 0;                                //此块内存分配失败次数
  
      size = size - sizeof(ngx_pool_t);               //去掉ngx_pool_t内存池的实际大小
      p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;//最大内存池节点大小为4095
  
      p->current = p;                                 //current指向p
      p->chain = NULL;
      p->large = NULL;
      p->cleanup = NULL;
      p->log = log;
  
      return p;
  }

The initialization structure is as shown below:

The green line indicates the structure members, for example, the members of ngx_pool_data_t include last, end, next, failed

The black line Represents the address pointed by the pointer

1 max selects the smallest one between size-sizeof(ngx_pool_t) and 4095

2 log calls the ngx_log_t structure created by ngx_log_init in main (that is, the global ngx_log object)

Principle:

The starting position where nginx actually allocates space from this memory pool starts from d.last. As the memory pool space is allocated externally, the pointer of this field will move backward.

Memory pool allocation

void *
 ngx_palloc(ngx_pool_t *pool, size_t size)
 {  
     u_char      *m;
     ngx_pool_t  *p;       
 
     //如果申请的内存大小小于创建的内存池节点大小(当然是去掉ngx_pool_t后)
     if (size <= pool->max) {
 
         p = pool->current;
 
         do {
             m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);//首先对齐last指针
 
             if ((size_t) (p->d.end - m) >= size) {
                 p->d.last = m + size;          
 
                 return m;
             }
 
             p = p->d.next;
 
         } while (p);
 
         return ngx_palloc_block(pool, size);
     }                                                                                                                                                              
 
     return ngx_palloc_large(pool, size);
 }

ngx_palloc() tries to allocate space from the pool memory There are two situations when allocating space of size size in the pool.

In the first case, if the allocated size is smaller than ngx_pool_t.max (small block allocation, code 127-140), you first need to align the last 16 bits. If there is still space in the application, then use this memory node (code 130) ) at the same time moves last to point to the allocated address, and returns the requested memory to the caller. If there is no space that can be allocated when traversing the small memory node from current (that is, traversing the linked list until the memory pool node next is empty). You need to allocate a memory pool node and call ngx_palloc_block(pool,size)

This function mainly allocates a memory pool node, then inserts this node into the end of the linked list, and updates the pool->current pointer at the same time. The update algorithm is to traverse the linked list. If it is found If this node has failed to be allocated 6 times, current will point to the next node. If all nodes have failed more than 6 times, current will point to the newly allocated node.

The core code is as follows:

current = pool->current;//初始化
 
     for (p = current; p->d.next; p = p->d.next) {//遍历
         if (p->d.failed++ > 4) {//分配超过6次
             current = p->d.next;
         }
     }
 
     p->d.next = new;//插入新节点                                                                                                                          
 
     pool->current = current ? current : new;//更新current

In the second case, allocate a large block of memory and call malloc directly to allocate it. After allocation, traverse the pool->large linked list. If there is a large memory pool node and alloc is empty, then Hang the newly allocated memory on this node. If there is no such node, then allocate and insert the head of the linked list of p->large.

Clear callback function

where each node is

 struct ngx_pool_cleanup_s {
      ngx_pool_cleanup_pt   handler;//回调handler
      void                 *data;	//回调函数参数
      ngx_pool_cleanup_t   *next;	//指向下一个节点
  };
ngx_pool_cleanup_t *      
 ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)
 {
     ngx_pool_cleanup_t  *c;
    
     c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t));//分配一个节点
     if (c == NULL) {      
         return NULL;
     }
 
     if (size) {
         c->data = ngx_palloc(p, size); 
         if (c->data == NULL) {
             return NULL;
         }
 
     } else {
         c->data = NULL;
     }
 
     c->handler = NULL;
     c->next = p->cleanup;//插入链表头
 
     p->cleanup = c;//插入链表头部
 
     ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c);
 
     return c;                                                                                                                                                      
 }

The above introduces [nginx source code analysis] ngx memory pool implementation, including aspects of the content. I hope it will be helpful to friends who are interested in PHP tutorials.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn